You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tl...@apache.org on 2021/03/11 09:06:47 UTC

[ignite] branch sql-calcite updated: IGNITE-14275 SQL. Calcite: fix MapReduce aggregates for hash distribution

This is an automated email from the ASF dual-hosted git repository.

tledkov pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/sql-calcite by this push:
     new 73f6775  IGNITE-14275 SQL. Calcite: fix MapReduce aggregates for hash distribution
73f6775 is described below

commit 73f6775b4ad7e6469fad9aca40c9ad7749982eb7
Author: Yury Gerzhedovich <yg...@gridgain.com>
AuthorDate: Thu Mar 11 12:06:23 2021 +0300

    IGNITE-14275 SQL. Calcite: fix MapReduce aggregates for hash distribution
---
 .../query/calcite/exec/LogicalRelImplementor.java  |   8 +-
 .../query/calcite/exec/QueryTaskExecutorImpl.java  |   3 -
 .../query/calcite/externalize/RelJson.java         |   3 +-
 .../query/calcite/rel/IgniteAggregateBase.java     |   5 +
 .../processors/query/calcite/trait/TraitUtils.java |   1 -
 .../calcite/AbstractBasicIntegrationTest.java      |  11 +-
 .../query/calcite/AggregatesIntegrationTest.java   |  22 ++++
 .../query/calcite/MetadataIntegrationTest.java     |   4 +
 .../calcite/exec/rel/AbstractExecutionTest.java    |   1 -
 .../query/calcite/exec/rel/BaseAggregateTest.java  |   1 -
 .../planner/AbstractAggregatePlannerTest.java      |  88 +++++++++++++
 .../calcite/planner/AggregatePlannerTest.java      | 143 +--------------------
 ...gateTest.java => HashAggregatePlannerTest.java} |  44 ++++++-
 .../query/calcite/planner/PlannerTest.java         |   4 -
 .../calcite/planner/SortAggregatePlannerTest.java  |  55 ++++++++
 .../apache/ignite/testsuites/PlannerTestSuite.java |   6 +-
 16 files changed, 240 insertions(+), 159 deletions(-)

diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
index 6e628e7..0d21530 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
@@ -37,10 +37,9 @@ import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler.RowFa
 import org.apache.ignite.internal.processors.query.calcite.exec.exp.ExpressionFactory;
 import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AccumulatorWrapper;
 import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.AggregateType;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.HashAggregateNode;
-import org.apache.ignite.internal.processors.query.calcite.exec.rel.SortAggregateNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.CorrelatedNestedLoopJoinNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.FilterNode;
+import org.apache.ignite.internal.processors.query.calcite.exec.rel.HashAggregateNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.Inbox;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.IndexSpoolNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.LimitNode;
@@ -51,16 +50,16 @@ import org.apache.ignite.internal.processors.query.calcite.exec.rel.Node;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.Outbox;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.ProjectNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.ScanNode;
+import org.apache.ignite.internal.processors.query.calcite.exec.rel.SortAggregateNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.SortNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.TableSpoolNode;
 import org.apache.ignite.internal.processors.query.calcite.exec.rel.UnionAllNode;
 import org.apache.ignite.internal.processors.query.calcite.metadata.AffinityService;
 import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashAggregate;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortAggregate;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashAggregate;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexSpool;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteLimit;
@@ -76,6 +75,7 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRelVisitor;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortAggregate;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableSpool;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/QueryTaskExecutorImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/QueryTaskExecutorImpl.java
index e9bcab2..b0db389 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/QueryTaskExecutorImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/QueryTaskExecutorImpl.java
@@ -20,10 +20,7 @@ package org.apache.ignite.internal.processors.query.calcite.exec;
 import java.util.Objects;
 import java.util.UUID;
 
-import org.apache.ignite.failure.FailureContext;
-import org.apache.ignite.failure.FailureType;
 import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.processors.query.calcite.CalciteQueryProcessor;
 import org.apache.ignite.internal.processors.query.calcite.util.AbstractService;
 import org.apache.ignite.internal.processors.query.calcite.util.Commons;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java
index d33e838..af0d2cb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJson.java
@@ -90,7 +90,6 @@ import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.SqlSelectKeyword;
 import org.apache.calcite.sql.SqlSyntax;
 import org.apache.calcite.sql.SqlWindow;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.fun.SqlTrimFunction;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
@@ -504,7 +503,7 @@ class RelJson {
 
                 return rexBuilder.makeLiteral(literal, type, false);
             }
-            
+
             throw new UnsupportedOperationException("cannot convert to rex " + o);
         }
         else if (o instanceof Boolean)
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregateBase.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregateBase.java
index 2380615..d2a40a4 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregateBase.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteAggregateBase.java
@@ -181,6 +181,7 @@ public abstract class IgniteAggregateBase extends IgniteAggregate implements Tra
                 if (isSimple(this)) {
                     ImmutableIntList keys = distribution.getKeys();
 
+                    //Check that group by contains all key columns
                     if (groupSet.cardinality() == keys.size()) {
                         Mappings.TargetMapping mapping = Commons.inverseMapping(
                             groupSet, getInput().getRowType().getFieldCount());
@@ -190,6 +191,10 @@ public abstract class IgniteAggregateBase extends IgniteAggregate implements Tra
                         if (outDistr.getType() == HASH_DISTRIBUTED)
                             res.add(Pair.of(nodeTraits.replace(outDistr), ImmutableList.of(in)));
                     }
+
+                    //Map-reduce aggregates especial for non 'group by' query, like a select count(*) from table
+                    if (groupSet.isEmpty())
+                        res.add(Pair.of(nodeTraits.replace(single()), ImmutableList.of(in.replace(hash(keys, distribution.function())))));
                 }
 
                 break;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/TraitUtils.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/TraitUtils.java
index b128566..602cb78 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/TraitUtils.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/TraitUtils.java
@@ -444,7 +444,6 @@ public class TraitUtils {
         return res;
     }
 
-
     /**
      * @param elem Elem.
      */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AbstractBasicIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AbstractBasicIntegrationTest.java
index 741f0f3..ceec400 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AbstractBasicIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AbstractBasicIntegrationTest.java
@@ -50,7 +50,14 @@ public class AbstractBasicIntegrationTest extends GridCommonAbstractTest {
         for (Ignite ign : G.allGrids()) {
             for (String cacheName : ign.cacheNames())
                 ign.destroyCache(cacheName);
+        }
+
+        cleanQueryPlanCache();
+    }
 
+    /** */
+    protected void cleanQueryPlanCache() {
+        for (Ignite ign : G.allGrids()) {
             CalciteQueryProcessor qryProc = (CalciteQueryProcessor)Commons.lookupComponent(
                 ((IgniteEx)ign).context(), QueryEngine.class);
 
@@ -68,7 +75,7 @@ public class AbstractBasicIntegrationTest extends GridCommonAbstractTest {
     }
 
     /** */
-    protected void createAndPopulateTable() {
+    protected IgniteCache<Integer, Employer> createAndPopulateTable() {
         IgniteCache<Integer, Employer> person = client.getOrCreateCache(new CacheConfiguration<Integer, Employer>()
             .setName("person")
             .setSqlSchema("PUBLIC")
@@ -82,6 +89,8 @@ public class AbstractBasicIntegrationTest extends GridCommonAbstractTest {
         person.put(idx++, new Employer("Ilya", 15d));
         person.put(idx++, new Employer("Roma", 10d));
         person.put(idx++, new Employer("Roma", 10d));
+
+        return person;
     }
 
     /** */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AggregatesIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AggregatesIntegrationTest.java
index 5a0dfe8..26cef02 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AggregatesIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/AggregatesIntegrationTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.query.calcite;
 
+import org.apache.ignite.IgniteCache;
+import org.hamcrest.Matcher;
 import org.junit.Test;
 
 /**
@@ -41,6 +43,7 @@ public class AggregatesIntegrationTest extends AbstractBasicIntegrationTest {
         assertQuery("select count(name) from person where salary > 10").returns(1L).check();
         assertQuery("select count(*) from person where salary > 10").returns(2L).check();
         assertQuery("select count(1) from person where salary > 10").returns(2L).check();
+        assertQuery("select count(*) from person where name is not null").returns(4L).check();
 
         assertQuery("select count(name) filter (where salary > 10) from person").returns(1L).check();
         assertQuery("select count(*) filter (where salary > 10) from person").returns(2L).check();
@@ -75,5 +78,24 @@ public class AggregatesIntegrationTest extends AbstractBasicIntegrationTest {
 
         assertQuery("select salary, count(name) from person group by salary having salary < 10 order by salary")
             .check();
+
+        assertQuery("select count(_key), _key from person group by _key")
+            .returns(1L, 0)
+            .returns(1L, 1)
+            .returns(1L, 2)
+            .returns(1L, 3)
+            .returns(1L, 4)
+            .check();
+
+        assertQuery("select count(name), name from person group by name")
+            .returns(1L, "Igor")
+            .returns(1L, "Ilya")
+            .returns(2L, "Roma")
+            .returns(0L, null)
+            .check();
+
+        assertQuery("select avg(salary) from person")
+            .returns(12.0)
+            .check();
     }
 }
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/MetadataIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/MetadataIntegrationTest.java
index ab84800..3cbf275 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/MetadataIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/MetadataIntegrationTest.java
@@ -43,6 +43,10 @@ public class MetadataIntegrationTest extends AbstractBasicIntegrationTest {
     public void columnNames() {
         createAndPopulateTable();
 
+        assertQuery("select count(_key), _key from person group by _key")
+            .columnNames("COUNT(_KEY)","_KEY")
+            .check();
+
         assertQuery("select (select count(*) from person), (select avg(salary) from person) from person")
             .columnNames("EXPR$0", "EXPR$1").check();
         assertQuery("select (select count(*) from person) as subquery from person")
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
index a490e6c..d5d1b80 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/AbstractExecutionTest.java
@@ -371,7 +371,6 @@ public class AbstractExecutionTest extends GridCommonAbstractTest {
             this.fieldCreators = fieldCreators;
         }
 
-
         /** */
         private static Object field(Integer rowNum) {
             return "val_" + rowNum;
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/BaseAggregateTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/BaseAggregateTest.java
index 4ef09e6..7f18597 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/BaseAggregateTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/BaseAggregateTest.java
@@ -360,7 +360,6 @@ public abstract class BaseAggregateTest extends AbstractExecutionTest {
         }
     }
 
-
     /** */
     private SingleNode<Object[]> createAggregateNodesChain(
         ExecutionContext<Object[]> ctx,
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractAggregatePlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractAggregatePlannerTest.java
new file mode 100644
index 0000000..ad98770
--- /dev/null
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractAggregatePlannerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.planner;
+
+import java.util.Arrays;
+
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
+import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
+import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
+import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeSystem;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ *
+ */
+@SuppressWarnings({"TypeMayBeWeakened"})
+public class AbstractAggregatePlannerTest extends AbstractPlannerTest {
+    /**
+     * @return REPLICATED test table (ID, VAL0, VAL1, GRP0, GRP1)
+     */
+    @NotNull protected TestTable createBroadcastTable() {
+        IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
+
+        TestTable tbl = new TestTable(
+            new RelDataTypeFactory.Builder(f)
+                .add("ID", f.createJavaType(Integer.class))
+                .add("VAL0", f.createJavaType(Integer.class))
+                .add("VAL1", f.createJavaType(Integer.class))
+                .add("GRP0", f.createJavaType(Integer.class))
+                .add("GRP1", f.createJavaType(Integer.class))
+                .build()) {
+
+            @Override public IgniteDistribution distribution() {
+                return IgniteDistributions.broadcast();
+            }
+        };
+        return tbl;
+    }
+
+    /**
+     * @return PARTITIONED test table (ID, VAL0, VAL1, GRP0, GRP1)
+     */
+    @NotNull protected AbstractPlannerTest.TestTable createAffinityTable() {
+        IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
+
+        return new TestTable(
+            new RelDataTypeFactory.Builder(f)
+                .add("ID", f.createJavaType(Integer.class))
+                .add("VAL0", f.createJavaType(Integer.class))
+                .add("VAL1", f.createJavaType(Integer.class))
+                .add("GRP0", f.createJavaType(Integer.class))
+                .add("GRP1", f.createJavaType(Integer.class))
+                .build()) {
+
+            @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
+                return ColocationGroup.forAssignments(Arrays.asList(
+                    select(nodes, 0, 1),
+                    select(nodes, 1, 2),
+                    select(nodes, 2, 0),
+                    select(nodes, 0, 1),
+                    select(nodes, 1, 2)
+                ));
+            }
+
+            @Override public IgniteDistribution distribution() {
+                return IgniteDistributions.affinity(0, "test", "hash");
+            }
+        };
+    }
+}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AggregatePlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AggregatePlannerTest.java
index f630ade..3ba52ba 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AggregatePlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AggregatePlannerTest.java
@@ -17,20 +17,15 @@
 
 package org.apache.ignite.internal.processors.query.calcite.planner;
 
-import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import org.apache.calcite.plan.RelOptPlanner;
 import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.sql.fun.SqlAvgAggFunction;
 import org.apache.calcite.util.ImmutableIntList;
-import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
-import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregate;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteAggregateBase;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashAggregate;
@@ -44,12 +39,9 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortAggregate;
 import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
 import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
 import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeSystem;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.testframework.GridTestUtils;
 import org.hamcrest.core.IsInstanceOf;
 import org.junit.Assert;
 import org.junit.Ignore;
@@ -62,7 +54,7 @@ import org.junit.runners.Parameterized;
  */
 @SuppressWarnings({"TypeMayBeWeakened"})
 @RunWith(Parameterized.class)
-public class AggregatePlannerTest extends AbstractPlannerTest {
+public class AggregatePlannerTest extends AbstractAggregatePlannerTest {
     /** Algorithm. */
     @Parameterized.Parameter
     public AggregateAlgorithm algo;
@@ -78,22 +70,7 @@ public class AggregatePlannerTest extends AbstractPlannerTest {
      */
     @Test
     public void singleWithoutIndex() throws Exception {
-        IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
-
-        TestTable tbl = new TestTable(
-            new RelDataTypeFactory.Builder(f)
-                .add("ID", f.createJavaType(Integer.class))
-                .add("VAL0", f.createJavaType(Integer.class))
-                .add("VAL1", f.createJavaType(Integer.class))
-                .add("GRP0", f.createJavaType(Integer.class))
-                .add("GRP1", f.createJavaType(Integer.class))
-                .build()) {
-
-            @Override public IgniteDistribution distribution() {
-                return IgniteDistributions.broadcast();
-            }
-        }
-            .addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
+        TestTable tbl = createBroadcastTable().addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
 
         IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
 
@@ -129,20 +106,7 @@ public class AggregatePlannerTest extends AbstractPlannerTest {
     public void singleWithIndex() throws Exception {
         IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
 
-        TestTable tbl = new TestTable(
-            new RelDataTypeFactory.Builder(f)
-                .add("ID", f.createJavaType(Integer.class))
-                .add("VAL0", f.createJavaType(Integer.class))
-                .add("VAL1", f.createJavaType(Integer.class))
-                .add("GRP0", f.createJavaType(Integer.class))
-                .add("GRP1", f.createJavaType(Integer.class))
-                .build()) {
-
-            @Override public IgniteDistribution distribution() {
-                return IgniteDistributions.broadcast();
-            }
-        }
-            .addIndex(RelCollations.of(ImmutableIntList.of(3, 4)), "grp0_grp1");
+        TestTable tbl = createBroadcastTable().addIndex(RelCollations.of(ImmutableIntList.of(3, 4)), "grp0_grp1");
 
         IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
 
@@ -176,31 +140,7 @@ public class AggregatePlannerTest extends AbstractPlannerTest {
      */
     @Test
     public void mapReduceGroupBy() throws Exception {
-        IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
-
-        TestTable tbl = new TestTable(
-            new RelDataTypeFactory.Builder(f)
-                .add("ID", f.createJavaType(Integer.class))
-                .add("VAL0", f.createJavaType(Integer.class))
-                .add("VAL1", f.createJavaType(Integer.class))
-                .add("GRP0", f.createJavaType(Integer.class))
-                .add("GRP1", f.createJavaType(Integer.class))
-                .build()) {
-
-            @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
-                return ColocationGroup.forAssignments(Arrays.asList(
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2),
-                    select(nodes, 2, 0),
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2)
-                ));
-            }
-
-            @Override public IgniteDistribution distribution() {
-                return IgniteDistributions.affinity(0, "test", "hash");
-            }
-        };
+        TestTable tbl = createAffinityTable();
 
         IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
 
@@ -245,30 +185,7 @@ public class AggregatePlannerTest extends AbstractPlannerTest {
     public void mapReduceDistinctWithIndex() throws Exception {
         IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
 
-        TestTable tbl = new TestTable(
-            new RelDataTypeFactory.Builder(f)
-                .add("ID", f.createJavaType(Integer.class))
-                .add("VAL0", f.createJavaType(Integer.class))
-                .add("VAL1", f.createJavaType(Integer.class))
-                .add("GRP0", f.createJavaType(Integer.class))
-                .add("GRP1", f.createJavaType(Integer.class))
-                .build()) {
-
-            @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
-                return ColocationGroup.forAssignments(Arrays.asList(
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2),
-                    select(nodes, 2, 0),
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2)
-                ));
-            }
-
-            @Override public IgniteDistribution distribution() {
-                return IgniteDistributions.affinity(0, "test", "hash");
-            }
-        }
-            .addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
+        TestTable tbl = createAffinityTable().addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
 
         IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
 
@@ -303,56 +220,6 @@ public class AggregatePlannerTest extends AbstractPlannerTest {
     }
 
     /** */
-    @Test
-    public void notApplicableForSortAggregate() {
-        if (algo == AggregateAlgorithm.HASH)
-            return;
-
-        IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
-
-        TestTable tbl = new TestTable(
-            new RelDataTypeFactory.Builder(f)
-                .add("ID", f.createJavaType(Integer.class))
-                .add("VAL0", f.createJavaType(Integer.class))
-                .add("VAL1", f.createJavaType(Integer.class))
-                .add("GRP0", f.createJavaType(Integer.class))
-                .add("GRP1", f.createJavaType(Integer.class))
-                .build()) {
-
-            @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
-                return ColocationGroup.forAssignments(Arrays.asList(
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2),
-                    select(nodes, 2, 0),
-                    select(nodes, 0, 1),
-                    select(nodes, 1, 2)
-                ));
-            }
-
-            @Override public IgniteDistribution distribution() {
-                return IgniteDistributions.affinity(0, "test", "hash");
-            }
-        }
-            .addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
-
-        IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
-
-        publicSchema.addTable("TEST", tbl);
-
-        String sql = "SELECT MIN(val0) FROM test";
-
-        GridTestUtils.assertThrows(log,
-            () -> physicalPlan(
-                sql,
-                publicSchema,
-                "HashAggregateConverterRule"
-            ),
-            RelOptPlanner.CannotPlanException.class,
-            "There are not enough rules to produce a node with desired properties"
-        );
-    }
-
-    /** */
     enum AggregateAlgorithm {
         /** */
         SORT(
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregateTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregatePlannerTest.java
similarity index 72%
rename from modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregateTest.java
rename to modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregatePlannerTest.java
index ff6f73e..e7596a4 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregateTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashAggregatePlannerTest.java
@@ -20,8 +20,11 @@ package org.apache.ignite.internal.processors.query.calcite.planner;
 import java.util.Arrays;
 
 import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelCollations;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.sql.fun.SqlAvgAggFunction;
+import org.apache.calcite.sql.fun.SqlCountAggFunction;
+import org.apache.calcite.util.ImmutableIntList;
 import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
 import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteMapHashAggregate;
@@ -41,12 +44,12 @@ import org.junit.Test;
  *
  */
 @SuppressWarnings({"TooBroadScope", "FieldCanBeLocal", "TypeMayBeWeakened"})
-public class HashAggregateTest extends AbstractPlannerTest {
+public class HashAggregatePlannerTest extends AbstractAggregatePlannerTest {
     /**
      * @throws Exception If failed.
      */
     @Test
-    public void test() throws Exception {
+    public void subqueryWithAggregate() throws Exception {
         IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
 
         TestTable employer = new TestTable(
@@ -99,7 +102,42 @@ public class HashAggregateTest extends AbstractPlannerTest {
             "Invalid plan\n" + RelOptUtil.toString(phys),
             F.first(mapAgg.getAggCallList()).getAggregation(),
             IsInstanceOf.instanceOf(SqlAvgAggFunction.class));
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void noGroupByAggregate() throws Exception {
+        TestTable tbl = createAffinityTable().addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
+
+        IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
+
+        publicSchema.addTable("TEST", tbl);
+
+        String sqlCount = "SELECT COUNT(*) FROM test";
+
+        IgniteRel phys = physicalPlan(
+            sqlCount,
+            publicSchema
+        );
+
+        checkSplitAndSerialization(phys, publicSchema);
 
-        System.out.println("+++\n" + RelOptUtil.toString(phys));
+        IgniteMapHashAggregate mapAgg = findFirstNode(phys, byClass(IgniteMapHashAggregate.class));
+        IgniteReduceHashAggregate rdcAgg = findFirstNode(phys, byClass(IgniteReduceHashAggregate.class));
+
+        assertNotNull("Invalid plan\n" + RelOptUtil.toString(phys), rdcAgg);
+        assertNotNull("Invalid plan\n" + RelOptUtil.toString(phys), mapAgg);
+
+        Assert.assertThat(
+            "Invalid plan\n" + RelOptUtil.toString(phys),
+            F.first(rdcAgg.aggregateCalls()).getAggregation(),
+            IsInstanceOf.instanceOf(SqlCountAggFunction.class));
+
+        Assert.assertThat(
+            "Invalid plan\n" + RelOptUtil.toString(phys),
+            F.first(mapAgg.getAggCallList()).getAggregation(),
+            IsInstanceOf.instanceOf(SqlCountAggFunction.class));
     }
 }
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java
index a15470f..08a2595 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/PlannerTest.java
@@ -41,9 +41,6 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelRoot;
 import org.apache.calcite.rel.RelVisitor;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rex.RexFieldAccess;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.util.ImmutableBitSet;
@@ -74,7 +71,6 @@ import org.apache.ignite.internal.processors.query.calcite.prepare.QueryTemplate
 import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexSpool;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteLimit;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
 import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/SortAggregatePlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/SortAggregatePlannerTest.java
new file mode 100644
index 0000000..d5bd8a6
--- /dev/null
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/SortAggregatePlannerTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.planner;
+
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.util.ImmutableIntList;
+import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.junit.Test;
+
+/**
+ *
+ */
+@SuppressWarnings({"FieldCanBeLocal"})
+public class SortAggregatePlannerTest extends AbstractAggregatePlannerTest {
+    /**
+     *
+     */
+    @Test
+    public void notApplicableForSortAggregate() {
+        TestTable tbl = createAffinityTable().addIndex(RelCollations.of(ImmutableIntList.of(1, 2)), "val0_val1");
+
+        IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
+
+        publicSchema.addTable("TEST", tbl);
+
+        String sqlMin = "SELECT MIN(val0) FROM test";
+
+        GridTestUtils.assertThrows(log,
+            () -> physicalPlan(
+                sqlMin,
+                publicSchema,
+                "HashAggregateConverterRule"
+            ),
+            RelOptPlanner.CannotPlanException.class,
+            "There are not enough rules to produce a node with desired properties"
+        );
+    }
+}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java b/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
index 959021f..4c7f024 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
@@ -17,10 +17,12 @@
 
 package org.apache.ignite.testsuites;
 
+import org.apache.ignite.internal.processors.query.calcite.planner.AggregatePlannerTest;
 import org.apache.ignite.internal.processors.query.calcite.planner.CorrelatedNestedLoopJoinPlannerTest;
+import org.apache.ignite.internal.processors.query.calcite.planner.HashAggregatePlannerTest;
 import org.apache.ignite.internal.processors.query.calcite.planner.IndexSpoolPlannerTest;
 import org.apache.ignite.internal.processors.query.calcite.planner.PlannerTest;
-import org.apache.ignite.internal.processors.query.calcite.planner.AggregatePlannerTest;
+import org.apache.ignite.internal.processors.query.calcite.planner.SortAggregatePlannerTest;
 import org.apache.ignite.internal.processors.query.calcite.planner.TableSpoolPlannerTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -35,6 +37,8 @@ import org.junit.runners.Suite;
     TableSpoolPlannerTest.class,
     IndexSpoolPlannerTest.class,
     AggregatePlannerTest.class,
+    HashAggregatePlannerTest.class,
+    SortAggregatePlannerTest.class,
 })
 public class PlannerTestSuite {
 }