You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/06/28 00:27:50 UTC
[3/7] git commit: Reduce count(not null) to count()
Reduce count(not null) to count()
Project: http://git-wip-us.apache.org/repos/asf/incubator-optiq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/4621db7e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-optiq/tree/4621db7e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-optiq/diff/4621db7e
Branch: refs/heads/master
Commit: 4621db7e4ee80dd84b14d448d05c093abb8a82f1
Parents: 347eabd
Author: Vladimir Sitnikov <si...@gmail.com>
Authored: Mon Jun 23 09:53:11 2014 +0400
Committer: Julian Hyde <ju...@gmail.com>
Committed: Sun Jun 22 23:54:38 2014 -0700
----------------------------------------------------------------------
.../rel/rules/ReduceAggregatesRule.java | 42 ++++++++++++++-----
.../main/java/org/eigenbase/rex/RexBuilder.java | 44 ++++++++++++++++++++
.../eigenbase/sql2rel/SqlToRelConverter.java | 10 ++++-
.../net/hydromatic/optiq/test/JdbcTest.java | 23 ++++++++++
.../org/eigenbase/test/RelMetadataTest.java | 13 ++++--
.../org/eigenbase/test/RelOptRulesTest.xml | 2 +-
.../eigenbase/test/SqlToRelConverterTest.xml | 4 +-
7 files changed, 119 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/main/java/org/eigenbase/rel/rules/ReduceAggregatesRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rel/rules/ReduceAggregatesRule.java b/core/src/main/java/org/eigenbase/rel/rules/ReduceAggregatesRule.java
index 4dc29b9..be9020b 100644
--- a/core/src/main/java/org/eigenbase/rel/rules/ReduceAggregatesRule.java
+++ b/core/src/main/java/org/eigenbase/rel/rules/ReduceAggregatesRule.java
@@ -26,8 +26,11 @@ import org.eigenbase.reltype.*;
import org.eigenbase.rex.*;
import org.eigenbase.sql.*;
import org.eigenbase.sql.fun.*;
+import org.eigenbase.sql.type.SqlTypeUtil;
import org.eigenbase.util.*;
+import com.google.common.collect.ImmutableList;
+
/**
* Rule to reduce aggregates to simpler forms. Currently only AVG(x) to
* SUM(x)/COUNT(x), but eventually will handle others such as STDDEV.
@@ -49,11 +52,18 @@ public class ReduceAggregatesRule extends RelOptRule {
//~ Methods ----------------------------------------------------------------
+ @Override
+ public boolean matches(RelOptRuleCall call) {
+ if (!super.matches(call)) {
+ return false;
+ }
+ AggregateRelBase oldAggRel = (AggregateRelBase) call.rels[0];
+ return containsAvgStddevVarCall(oldAggRel.getAggCallList());
+ }
+
public void onMatch(RelOptRuleCall ruleCall) {
AggregateRelBase oldAggRel = (AggregateRelBase) ruleCall.rels[0];
- if (containsAvgStddevVarCall(oldAggRel.getAggCallList())) {
- reduceAggs(ruleCall, oldAggRel);
- }
+ reduceAggs(ruleCall, oldAggRel);
}
/**
@@ -200,11 +210,14 @@ public class ReduceAggregatesRule extends RelOptRule {
// anything else: preserve original call
RexBuilder rexBuilder = oldAggRel.getCluster().getRexBuilder();
final int nGroups = oldAggRel.getGroupCount();
+ List<RelDataType> oldArgTypes = SqlTypeUtil
+ .projectTypes(oldAggRel.getRowType(), oldCall.getArgList());
return rexBuilder.addAggCall(
oldCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ oldArgTypes);
}
}
@@ -251,13 +264,15 @@ public class ReduceAggregatesRule extends RelOptRule {
sumCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(avgInputType));
RexNode denominatorRef =
rexBuilder.addAggCall(
countCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(avgInputType));
final RexNode divideRef =
rexBuilder.makeCall(
SqlStdOperatorTable.DIVIDE,
@@ -309,7 +324,8 @@ public class ReduceAggregatesRule extends RelOptRule {
sumZeroCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(argType));
if (!oldCall.getType().isNullable()) {
// If SUM(x) is not nullable, the validator must have determined that
// nulls are impossible (because the group is never empty and x is never
@@ -321,7 +337,8 @@ public class ReduceAggregatesRule extends RelOptRule {
countCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(argType));
return rexBuilder.makeCall(SqlStdOperatorTable.CASE,
rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
countRef, rexBuilder.makeExactLiteral(BigDecimal.ZERO)),
@@ -382,7 +399,8 @@ public class ReduceAggregatesRule extends RelOptRule {
sumArgSquaredAggCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(argType));
final AggregateCall sumArgAggCall =
new AggregateCall(
@@ -396,7 +414,8 @@ public class ReduceAggregatesRule extends RelOptRule {
sumArgAggCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(argType));
final RexNode sumSquaredArg =
rexBuilder.makeCall(
@@ -416,7 +435,8 @@ public class ReduceAggregatesRule extends RelOptRule {
countArgAggCall,
nGroups,
newCalls,
- aggCallMapping);
+ aggCallMapping,
+ ImmutableList.of(argType));
final RexNode avgSumSquaredArg =
rexBuilder.makeCall(
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/main/java/org/eigenbase/rex/RexBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rex/RexBuilder.java b/core/src/main/java/org/eigenbase/rex/RexBuilder.java
index 6a848bc..a05df07 100644
--- a/core/src/main/java/org/eigenbase/rex/RexBuilder.java
+++ b/core/src/main/java/org/eigenbase/rex/RexBuilder.java
@@ -262,12 +262,56 @@ public class RexBuilder {
/**
* Creates a reference to an aggregate call, checking for repeated calls.
+ * @param aggCall aggregate call to be added
+ * @param groupCount number of groups in the aggregate relation
+ * @param aggCalls destination list of aggregate calls
+ * @param aggCallMapping the dictionary of already added calls
+ * @return Rex expression for the given aggregate call
+ * @deprecated Use {@link #addAggCall(org.eigenbase.rel.AggregateCall, int, java.util.List, java.util.Map, java.util.List)}
+ * Will be removed before optiq-0.9.
*/
+ @Deprecated
public RexNode addAggCall(
AggregateCall aggCall,
int groupCount,
List<AggregateCall> aggCalls,
Map<AggregateCall, RexNode> aggCallMapping) {
+ Bug.upgrade("remove before optiq-0.9");
+ return addAggCall(aggCall, groupCount, aggCalls, aggCallMapping, null);
+ }
+
+ /**
+ * Creates a reference to an aggregate call, checking for repeated calls.
+ * Argument types help to optimize for repeated aggregates.
+ * For instance count(42) is equivalent to count(*)
+ * @param aggCall aggregate call to be added
+ * @param groupCount number of groups in the aggregate relation
+ * @param aggCalls destination list of aggregate calls
+ * @param aggCallMapping the dictionary of already added calls
+ * @return Rex expression for the given aggregate call
+ */
+ public RexNode addAggCall(
+ AggregateCall aggCall,
+ int groupCount,
+ List<AggregateCall> aggCalls,
+ Map<AggregateCall, RexNode> aggCallMapping,
+ List<RelDataType> aggArgTypes) {
+ if (aggCall.getAggregation() instanceof SqlCountAggFunction
+ && aggArgTypes != null && !aggArgTypes.isEmpty()
+ && !aggCall.isDistinct()) {
+ boolean hasNotNullArg = false;
+ for (RelDataType type : aggArgTypes) {
+ if (!type.isNullable()) {
+ hasNotNullArg = true;
+ break;
+ }
+ }
+ if (hasNotNullArg) {
+ aggCall = new AggregateCall(aggCall.getAggregation(),
+ aggCall.isDistinct(), ImmutableList.<Integer>of(),
+ aggCall.getType(), aggCall.getName());
+ }
+ }
RexNode rex = aggCallMapping.get(aggCall);
if (rex == null) {
int index = aggCalls.size() + groupCount;
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java b/core/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
index 07f4650..682914d 100644
--- a/core/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/eigenbase/sql2rel/SqlToRelConverter.java
@@ -4556,6 +4556,10 @@ public class SqlToRelConverter {
if (call.getOperator().isAggregator()) {
assert bb.agg == this;
List<Integer> args = new ArrayList<Integer>();
+ List<RelDataType> argTypes =
+ call.getOperator() instanceof SqlCountAggFunction
+ ? new ArrayList<RelDataType>(call.getOperandList().size())
+ : null;
try {
// switch out of agg mode
bb.agg = null;
@@ -4573,6 +4577,9 @@ public class SqlToRelConverter {
}
convertedExpr = bb.convertExpression(operand);
assert convertedExpr != null;
+ if (argTypes != null) {
+ argTypes.add(convertedExpr.getType());
+ }
args.add(lookupOrCreateGroupExpr(convertedExpr));
}
} finally {
@@ -4601,7 +4608,8 @@ public class SqlToRelConverter {
aggCall,
groupExprs.size(),
aggCalls,
- aggCallMapping);
+ aggCallMapping,
+ argTypes);
aggMapping.put(call, rex);
} else if (call instanceof SqlSelect) {
// rchen 2006-10-17:
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java b/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
index 0fdf109..e02c19d 100644
--- a/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
+++ b/core/src/test/java/net/hydromatic/optiq/test/JdbcTest.java
@@ -2800,9 +2800,32 @@ public class JdbcTest {
+ " avg(\"deptno\") as a\n"
+ "from \"hr\".\"emps\"\n"
+ "where \"deptno\" < 0")
+ .explainContains(
+ "PLAN=EnumerableCalcRel(expr#0..2=[{inputs}], expr#3=[0], expr#4=[=($t0, $t3)], expr#5=[null], expr#6=[CASE($t4, $t5, $t1)], expr#7=[/($t2, $t0)], expr#8=[CAST($t7):JavaType(class java.lang.Integer)], CS=[$t0], C=[$t0], S=[$t6], A=[$t8])\n"
+ + " EnumerableAggregateRel(group=[{}], CS=[COUNT()], agg#1=[$SUM0($0)], agg#2=[SUM($0)])\n"
+ + " EnumerableCalcRel(expr#0..4=[{inputs}], expr#5=[0], expr#6=[<($t1, $t5)], deptno=[$t1], $condition=[$t6])\n"
+ + " EnumerableTableAccessRel(table=[[hr, emps]])\n")
.returns("CS=0; C=0; S=null; A=null\n");
}
+ /** Tests that count(deptno) is reduced to count(). */
+ @Test public void testReduceCountNotNullable() {
+ OptiqAssert.that()
+ .with(OptiqAssert.Config.REGULAR)
+ .query(
+ "select\n"
+ + " count(\"deptno\") as cs,\n"
+ + " count(*) as cs2\n"
+ + "from \"hr\".\"emps\"\n"
+ + "where \"deptno\" < 0")
+ .explainContains(
+ "PLAN=EnumerableCalcRel(expr#0=[{inputs}], CS=[$t0], CS2=[$t0])\n"
+ + " EnumerableAggregateRel(group=[{}], CS=[COUNT()])\n"
+ + " EnumerableCalcRel(expr#0..4=[{inputs}], expr#5=[0], expr#6=[<($t1, $t5)], DUMMY=[$t5], $condition=[$t6])\n"
+ + " EnumerableTableAccessRel(table=[[hr, emps]])\n")
+ .returns("CS=0; CS2=0\n");
+ }
+
/** Tests sorting by a column that is already sorted. */
@Test public void testOrderByOnSortedTable() {
OptiqAssert.that()
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/test/java/org/eigenbase/test/RelMetadataTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/eigenbase/test/RelMetadataTest.java b/core/src/test/java/org/eigenbase/test/RelMetadataTest.java
index 7b587fe..63be2f9 100644
--- a/core/src/test/java/org/eigenbase/test/RelMetadataTest.java
+++ b/core/src/test/java/org/eigenbase/test/RelMetadataTest.java
@@ -330,11 +330,16 @@ public class RelMetadataTest extends SqlToRelTestBase {
false);
}
- @Test public void testColumnOriginsAggMeasure() {
+ @Test public void testColumnOriginsAggReduced() {
+ checkNoColumnOrigin(
+ "select count(deptno),name from dept group by name");
+ }
+
+ @Test public void testColumnOriginsAggCountNullable() {
checkSingleColumnOrigin(
- "select count(deptno),name from dept group by name",
- "DEPT",
- "DEPTNO",
+ "select count(mgr),ename from emp group by ename",
+ "EMP",
+ "MGR",
true);
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
index 5976cc7..68ba466 100644
--- a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
@@ -107,7 +107,7 @@ AggregateRel(group=[{0}], EXPR$1=[MAX($0)], EXPR$2=[AVG($1)], EXPR$3=[MIN($0)])
<![CDATA[
ProjectRel(NAME=[$0], EXPR$1=[$1], EXPR$2=[CAST(/($2, $3)):INTEGER NOT NULL], EXPR$3=[$4])
ProjectRel(NAME=[$0], EXPR$1=[$1], $f2=[$2], $f3=[$3], EXPR$3=[$4])
- AggregateRel(group=[{0}], EXPR$1=[MAX($0)], agg#1=[$SUM0($1)], agg#2=[COUNT($1)], EXPR$3=[MIN($0)])
+ AggregateRel(group=[{0}], EXPR$1=[MAX($0)], agg#1=[$SUM0($1)], agg#2=[COUNT()], EXPR$3=[MIN($0)])
ProjectRel(NAME=[$1], DEPTNO=[$0])
TableAccessRel(table=[[CATALOG, SALES, DEPT]])
]]>
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/4621db7e/core/src/test/resources/org/eigenbase/test/SqlToRelConverterTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/eigenbase/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/eigenbase/test/SqlToRelConverterTest.xml
index c7bbdd5..c2cc97d 100644
--- a/core/src/test/resources/org/eigenbase/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/eigenbase/test/SqlToRelConverterTest.xml
@@ -63,7 +63,7 @@ ProjectRel(DEPTNO=[$0], EXPR$1=[$1])
<Resource name="plan">
<![CDATA[
ProjectRel(EXPR$0=[+($0, 4)], EXPR$1=[$1], EXPR$2=[$2], EXPR$3=[*(2, $3)])
- AggregateRel(group=[{0}], EXPR$1=[SUM($1)], EXPR$2=[SUM($2)], agg#2=[COUNT($1)])
+ AggregateRel(group=[{0}], EXPR$1=[SUM($1)], EXPR$2=[SUM($2)], agg#2=[COUNT()])
ProjectRel(DEPTNO=[$7], SAL=[$5], $f2=[+(3, $5)])
TableAccessRel(table=[[CATALOG, SALES, EMP]])
]]>
@@ -130,7 +130,7 @@ ProjectRel(NAME=[$0])
<![CDATA[
ProjectRel(NAME=[$1], FOO=[$2])
ProjectRel(DEPTNO=[$1], NAME=[$0], FOO=[$2])
- AggregateRel(group=[{0, 1}], FOO=[COUNT($1)])
+ AggregateRel(group=[{0, 1}], FOO=[COUNT()])
ProjectRel(NAME=[$1], DEPTNO=[$0])
TableAccessRel(table=[[CATALOG, SALES, DEPT]])
]]>