Repository: calcite
Updated Branches:
  refs/heads/master b8e09fe9a -> c48c34139


[CALCITE-845] Derive SUM’s return type by a customizable policy (Maryann Xue)


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/2fd8c5a4
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/2fd8c5a4
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/2fd8c5a4

Branch: refs/heads/master
Commit: 2fd8c5a462a4369a267cfc118fa87b03ccba6478
Parents: b8e09fe
Author: maryannxue <[email protected]>
Authored: Tue Nov 3 20:51:02 2015 -0800
Committer: Julian Hyde <[email protected]>
Committed: Wed Nov 4 10:33:33 2015 -0800

----------------------------------------------------------------------
 .../rel/rules/AggregateReduceFunctionsRule.java | 42 +++++++-------------
 .../calcite/rel/type/RelDataTypeSystem.java     |  6 +++
 .../calcite/rel/type/RelDataTypeSystemImpl.java |  5 +++
 .../calcite/sql/fun/SqlSumAggFunction.java      |  2 +-
 .../sql/fun/SqlSumEmptyIsZeroAggFunction.java   |  2 +-
 .../apache/calcite/sql/type/ReturnTypes.java    | 38 ++++++++++++++++++
 6 files changed, 66 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java
 
b/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java
index c1f2f7f..578ecde 100644
--- 
a/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java
+++ 
b/core/src/main/java/org/apache/calcite/rel/rules/AggregateReduceFunctionsRule.java
@@ -25,12 +25,10 @@ import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.logical.LogicalAggregate;
 import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.fun.SqlAvgAggFunction;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlSumAggFunction;
@@ -249,25 +247,21 @@ public class AggregateReduceFunctionsRule extends 
RelOptRule {
       List<AggregateCall> newCalls,
       Map<AggregateCall, RexNode> aggCallMapping) {
     final int nGroups = oldAggRel.getGroupCount();
-    RelDataTypeFactory typeFactory =
-        oldAggRel.getCluster().getTypeFactory();
     RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
     int iAvgInput = oldCall.getArgList().get(0);
     RelDataType avgInputType =
         getFieldType(
             oldAggRel.getInput(),
             iAvgInput);
-    RelDataType sumType =
-        typeFactory.createTypeWithNullability(
-            avgInputType,
-            avgInputType.isNullable() || nGroups == 0);
-    SqlAggFunction sumAgg = new SqlSumAggFunction(sumType);
     AggregateCall sumCall =
-        AggregateCall.create(sumAgg,
+        AggregateCall.create(
+            SqlStdOperatorTable.SUM,
             oldCall.isDistinct(),
             oldCall.getArgList(),
             oldCall.filterArg,
-            sumType,
+            oldAggRel.getGroupCount(),
+            oldAggRel.getInput(),
+            null,
             null);
     AggregateCall countCall =
         AggregateCall.create(
@@ -309,20 +303,16 @@ public class AggregateReduceFunctionsRule extends 
RelOptRule {
       List<AggregateCall> newCalls,
       Map<AggregateCall, RexNode> aggCallMapping) {
     final int nGroups = oldAggRel.getGroupCount();
-    RelDataTypeFactory typeFactory =
-        oldAggRel.getCluster().getTypeFactory();
     RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
     int arg = oldCall.getArgList().get(0);
     RelDataType argType =
         getFieldType(
             oldAggRel.getInput(),
             arg);
-    final RelDataType sumType =
-        typeFactory.createTypeWithNullability(
-            argType, argType.isNullable());
     final AggregateCall sumZeroCall =
         AggregateCall.create(SqlStdOperatorTable.SUM0, oldCall.isDistinct(),
-            oldCall.getArgList(), oldCall.filterArg, sumType, oldCall.name);
+            oldCall.getArgList(), oldCall.filterArg, oldAggRel.getGroupCount(),
+            oldAggRel.getInput(), null, oldCall.name);
     final AggregateCall countCall =
         AggregateCall.create(
             SqlStdOperatorTable.COUNT,
@@ -383,8 +373,6 @@ public class AggregateReduceFunctionsRule extends 
RelOptRule {
     //     / nullif(count(x) - 1, 0),
     //     .5)
     final int nGroups = oldAggRel.getGroupCount();
-    RelDataTypeFactory typeFactory =
-        oldAggRel.getCluster().getTypeFactory();
     final RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
 
     assert oldCall.getArgList().size() == 1 : oldCall.getArgList();
@@ -400,17 +388,15 @@ public class AggregateReduceFunctionsRule extends 
RelOptRule {
             SqlStdOperatorTable.MULTIPLY, argRef, argRef);
     final int argSquaredOrdinal = lookupOrAdd(inputExprs, argSquared);
 
-    final RelDataType sumType =
-        typeFactory.createTypeWithNullability(
-            argType,
-            true);
     final AggregateCall sumArgSquaredAggCall =
         AggregateCall.create(
-            new SqlSumAggFunction(sumType),
+            SqlStdOperatorTable.SUM,
             oldCall.isDistinct(),
             ImmutableIntList.of(argSquaredOrdinal),
             oldCall.filterArg,
-            sumType,
+            oldAggRel.getGroupCount(),
+            oldAggRel.getInput(),
+            null,
             null);
     final RexNode sumArgSquared =
         rexBuilder.addAggCall(sumArgSquaredAggCall,
@@ -422,11 +408,13 @@ public class AggregateReduceFunctionsRule extends 
RelOptRule {
 
     final AggregateCall sumArgAggCall =
         AggregateCall.create(
-            new SqlSumAggFunction(sumType),
+            SqlStdOperatorTable.SUM,
             oldCall.isDistinct(),
             ImmutableIntList.of(argOrdinal),
             oldCall.filterArg,
-            sumType,
+            oldAggRel.getGroupCount(),
+            oldAggRel.getInput(),
+            null,
             null);
     final RexNode sumArg =
         rexBuilder.addAggCall(sumArgAggCall,

http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java 
b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java
index cddaf94..34938f6 100644
--- a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java
+++ b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystem.java
@@ -67,6 +67,12 @@ public interface RelDataTypeSystem {
 
   /** Returns the numeric type Radix, 2 or 10. 0 represent not applicable*/
   int getNumTypeRadix(SqlTypeName typeName);
+
+  /**
+   * Returns the return type of SUM aggregate function inferred from its
+   * argument type.
+   */
+  RelDataType deriveSumType(RelDataTypeFactory typeFactory, RelDataType 
argumentType);
 }
 
 // End RelDataTypeSystem.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystemImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystemImpl.java 
b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystemImpl.java
index 4611b4b..b760829 100644
--- a/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystemImpl.java
+++ b/core/src/main/java/org/apache/calcite/rel/type/RelDataTypeSystemImpl.java
@@ -161,6 +161,11 @@ public abstract class RelDataTypeSystemImpl implements 
RelDataTypeSystem {
     }
     return 0;
   }
+
+  public RelDataType deriveSumType(
+      RelDataTypeFactory typeFactory, RelDataType argumentType) {
+    return argumentType;
+  }
 }
 
 // End RelDataTypeSystemImpl.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/sql/fun/SqlSumAggFunction.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlSumAggFunction.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlSumAggFunction.java
index 0fc6606..48e8ea4 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlSumAggFunction.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlSumAggFunction.java
@@ -48,7 +48,7 @@ public class SqlSumAggFunction extends SqlAggFunction {
         "SUM",
         null,
         SqlKind.OTHER_FUNCTION,
-        ReturnTypes.ARG0_NULLABLE_IF_EMPTY,
+        ReturnTypes.AGG_SUM,
         null,
         OperandTypes.NUMERIC,
         SqlFunctionCategory.NUMERIC,

http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/sql/fun/SqlSumEmptyIsZeroAggFunction.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlSumEmptyIsZeroAggFunction.java
 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlSumEmptyIsZeroAggFunction.java
index 9cb3459..5b673e2 100644
--- 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlSumEmptyIsZeroAggFunction.java
+++ 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlSumEmptyIsZeroAggFunction.java
@@ -43,7 +43,7 @@ public class SqlSumEmptyIsZeroAggFunction extends 
SqlAggFunction {
     super("$SUM0",
         null,
         SqlKind.OTHER_FUNCTION,
-        ReturnTypes.ARG0,
+        ReturnTypes.AGG_SUM_EMPTY_IS_ZERO,
         null,
         OperandTypes.NUMERIC,
         SqlFunctionCategory.NUMERIC,

http://git-wip-us.apache.org/repos/asf/calcite/blob/2fd8c5a4/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java 
b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
index 0a755c6..fa99579 100644
--- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java
@@ -727,6 +727,44 @@ public abstract class ReturnTypes {
               true);
         }
       };
+
+  /**
+   * Type-inference strategy for SUM aggregate function inferred from the
+   * operand type, and nullable if the call occurs within a "GROUP BY ()"
+   * query. E.g. in "select sum(x) as s from empty", s may be null. Also,
+   * with the default implementation of RelDataTypeSystem, s has the same
+   * type name as x.
+   */
+  public static final SqlReturnTypeInference AGG_SUM =
+      new SqlReturnTypeInference() {
+        @Override public RelDataType
+        inferReturnType(SqlOperatorBinding opBinding) {
+          final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
+          final RelDataType type = typeFactory.getTypeSystem()
+              .deriveSumType(typeFactory, opBinding.getOperandType(0));
+          if (opBinding.getGroupCount() == 0 || opBinding.hasFilter()) {
+            return typeFactory.createTypeWithNullability(type, true);
+          } else {
+            return type;
+          }
+        }
+      };
+
+  /**
+   * Type-inference strategy for $SUM0 aggregate function inferred from the
+   * operand type. By default the inferred type is identical to the operand
+   * type. E.g. in "select $sum0(x) as s from empty", s has the same type as
+   * x.
+   */
+  public static final SqlReturnTypeInference AGG_SUM_EMPTY_IS_ZERO =
+      new SqlReturnTypeInference() {
+        @Override public RelDataType
+        inferReturnType(SqlOperatorBinding opBinding) {
+          final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
+          return typeFactory.getTypeSystem()
+              .deriveSumType(typeFactory, opBinding.getOperandType(0));
+        }
+      };
 }
 
 // End ReturnTypes.java

Reply via email to