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
