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

zstan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 0406832da8 IGNITE-18569 Fix planning with MRSortAggregate - Fixes 
#1603.
0406832da8 is described below

commit 0406832da86aaf225d3bb8bf7de8e1701ad6df00
Author: zstan <[email protected]>
AuthorDate: Fri Feb 3 09:13:51 2023 +0300

    IGNITE-18569 Fix planning with MRSortAggregate - Fixes #1603.
    
    Signed-off-by: zstan <[email protected]>
---
 .../internal/sql/engine/ItAggregatesTest.java      | 365 ++++++++++++++++++---
 .../internal/sql/engine/ItSortAggregateTest.java   | 208 ------------
 .../sql/engine/exec/LogicalRelImplementor.java     |  16 +-
 .../sql/engine/exec/rel/SortAggregateNode.java     |   8 +-
 .../sql/engine/metadata/ColocationGroup.java       |   2 +-
 .../sql/engine/metadata/FragmentMapping.java       |   2 +-
 .../sql/engine/rel/IgniteHashIndexSpool.java       |   2 +-
 .../rel/agg/IgniteColocatedAggregateBase.java      |  10 +-
 .../rel/agg/IgniteColocatedHashAggregate.java      |   5 +
 .../rel/agg/IgniteColocatedSortAggregate.java      |   5 +-
 .../sql/engine/rel/agg/IgniteMapAggregateBase.java |  11 -
 .../sql/engine/rel/agg/IgniteMapHashAggregate.java |   5 +-
 .../sql/engine/rel/agg/IgniteMapSortAggregate.java |   7 +-
 .../engine/rel/agg/IgniteReduceAggregateBase.java  |   5 +-
 .../engine/rel/agg/IgniteReduceHashAggregate.java  |   5 +-
 .../engine/rel/agg/IgniteReduceSortAggregate.java  |   2 -
 .../engine/rule/SortAggregateConverterRule.java    |   6 +-
 .../sql/engine/planner/AggregatePlannerTest.java   |   2 +-
 .../engine/planner/HashAggregatePlannerTest.java   |   6 +-
 19 files changed, 369 insertions(+), 303 deletions(-)

diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
index 476741c487..e28ca50ff2 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItAggregatesTest.java
@@ -21,95 +21,158 @@ import static 
org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.stream.Stream;
 import org.apache.ignite.internal.sql.engine.util.QueryChecker;
+import org.apache.ignite.internal.testframework.WithSystemProperty;
 import org.apache.ignite.lang.IgniteException;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 /**
  * Group of tests to verify aggregation functions.
  */
 public class ItAggregatesTest extends AbstractBasicIntegrationTest {
+    private static String[] disabledRules = 
{"MapReduceHashAggregateConverterRule", "MapReduceSortAggregateConverterRule",
+            "ColocatedHashAggregateConverterRule", 
"ColocatedSortAggregateConverterRule"};
+
+    private static final int ROWS = 103;
+
     /**
      * Before all.
      */
     @BeforeAll
-    static void initTestData() {
+    static void initTestData() throws InterruptedException {
         createAndPopulateTable();
+
+        sql("CREATE TABLE test (id INT PRIMARY KEY, grp0 INT, grp1 INT, val0 
INT, val1 INT) WITH replicas=2,partitions=10");
+        sql("CREATE TABLE test_one_col_idx (pk INT PRIMARY KEY, col0 INT)");
+
+        sql("CREATE INDEX test_idx ON test(grp0, grp1)");
+        sql("CREATE INDEX test_one_col_idx_idx ON test_one_col_idx(col0)");
+
+        // FIXME: https://issues.apache.org/jira/browse/IGNITE-18203
+        waitForIndex("test_idx");
+        waitForIndex("test_one_col_idx_idx");
+
+        for (int i = 0; i < ROWS; i++) {
+            sql("INSERT INTO test (id, grp0, grp1, val0, val1) VALUES (?, ?, 
?, ?, ?)", i, i / 10, i / 100, 1, 2);
+            sql("INSERT INTO test_one_col_idx (pk, col0) VALUES (?, ?)", i, i);
+        }
     }
 
-    @Test
-    public void countOfNonNumericField() {
-        assertQuery("select count(name) from person").returns(4L).check();
-        assertQuery("select count(*) from person").returns(5L).check();
-        assertQuery("select count(1) from person").returns(5L).check();
-        assertQuery("select count(null) from person").returns(0L).check();
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void aggregateWithSumAndHaving(String[] rules) {
+        var res = sql(
+                appendDisabledRules("SELECT SUM(val0), SUM(val1), grp0 FROM 
TEST GROUP BY grp0 HAVING SUM(val1) > 10", rules));
+
+        assertEquals(ROWS / 10, res.size());
 
-        assertQuery("select count(*) from person where salary < 
0").returns(0L).check();
-        assertQuery("select count(*) from person where salary < 0 and salary > 
0").returns(0L).check();
+        res.forEach(r -> {
+            long s0 = (Long) r.get(0);
+            long s1 = (Long) r.get(1);
 
-        assertQuery("select count(case when name like 'R%' then 1 else null 
end) from person").returns(2L).check();
-        assertQuery("select count(case when name not like 'I%' then 1 else 
null end) from person").returns(2L).check();
+            assertEquals(s0 * 2, s1);
+        });
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void correctCollationsOnAgg(String[] rules) {
+        var cursors = sql(
+                appendDisabledRules("SELECT PK FROM TEST_ONE_COL_IDX WHERE 
col0 IN (SELECT col0 FROM TEST_ONE_COL_IDX)", rules));
 
-        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();
+        assertEquals(ROWS, cursors.size());
+    }
 
-        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();
-        assertQuery("select count(1) filter (where salary > 10) from 
person").returns(2L).check();
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void countOfNonNumericField(String[] rules) {
+        assertQuery("select count(name) from 
person").disableRules(rules).returns(4L).check();
+        assertQuery("select count(*) from 
person").disableRules(rules).returns(5L).check();
+        assertQuery("select count(1) from 
person").disableRules(rules).returns(5L).check();
+        assertQuery("select count(null) from 
person").disableRules(rules).returns(0L).check();
+
+        assertQuery("select count(*) from person where salary < 
0").disableRules(rules).returns(0L).check();
+        assertQuery("select count(*) from person where salary < 0 and salary > 
0").disableRules(rules).returns(0L).check();
+
+        assertQuery("select count(case when name like 'R%' then 1 else null 
end) from person").disableRules(rules).returns(2L).check();
+        assertQuery("select count(case when name not like 'I%' then 1 else 
null end) from person").disableRules(rules).returns(2L).check();
+
+        assertQuery("select count(name) from person where salary > 
10").disableRules(rules).returns(1L).check();
+        assertQuery("select count(*) from person where salary > 
10").disableRules(rules).returns(2L).check();
+        assertQuery("select count(1) from person where salary > 
10").disableRules(rules).returns(2L).check();
+        assertQuery("select count(*) from person where name is not 
null").disableRules(rules).returns(4L).check();
+
+        assertQuery("select count(name) filter (where salary > 10) from 
person").disableRules(rules).returns(1L).check();
+        assertQuery("select count(*) filter (where salary > 10) from 
person").disableRules(rules).returns(2L).check();
+        assertQuery("select count(1) filter (where salary > 10) from 
person").disableRules(rules).returns(2L).check();
 
         assertQuery("select salary, count(name) from person group by salary 
order by salary")
+                .disableRules(rules)
                 .returns(10d, 3L)
                 .returns(15d, 1L)
                 .check();
 
         // same query, but grouping by alias
         assertQuery("select salary as sal, count(name) from person group by 
sal order by sal")
+                .disableRules(rules)
                 .returns(10d, 3L)
                 .returns(15d, 1L)
                 .check();
 
         // same query, but grouping by ordinal
         assertQuery("select salary, count(name) from person group by 1 order 
by 1")
+                .disableRules(rules)
                 .returns(10d, 3L)
                 .returns(15d, 1L)
                 .check();
 
         assertQuery("select salary * salary / 5, count(name) from person group 
by (salary * salary / 5) order by (salary * salary / 5)")
+                .disableRules(rules)
                 .returns(20d, 3L)
                 .returns(45d, 1L)
                 .check();
 
         // same query, but grouping by alias
         assertQuery("select (salary * salary / 5) as sal, count(name) from 
person group by sal order by sal")
+                .disableRules(rules)
                 .returns(20d, 3L)
                 .returns(45d, 1L)
                 .check();
 
         // same query, but grouping by ordinal
         assertQuery("select salary * salary / 5, count(name) from person group 
by 1 order by 1")
+                .disableRules(rules)
                 .returns(20d, 3L)
                 .returns(45d, 1L)
                 .check();
 
         assertQuery("select salary, count(*) from person group by salary order 
by salary")
+                .disableRules(rules)
                 .returns(10d, 3L)
                 .returns(15d, 2L)
                 .check();
 
         assertQuery("select salary, count(1) from person group by salary order 
by salary")
+                .disableRules(rules)
                 .returns(10d, 3L)
                 .returns(15d, 2L)
                 .check();
 
         assertQuery("select salary, count(1), sum(1) from person group by 
salary order by salary")
+                .disableRules(rules)
                 .returns(10d, 3L, 3L)
                 .returns(15d, 2L, 2L)
                 .check();
 
         assertQuery("select salary, name, count(1), sum(salary) from person 
group by salary, name order by salary")
+                .disableRules(rules)
                 .returns(10d, "Igor", 1L, 10d)
                 .returns(10d, "Roma", 2L, 20d)
                 .returns(15d, "Ilya", 1L, 15d)
@@ -117,9 +180,11 @@ public class ItAggregatesTest extends 
AbstractBasicIntegrationTest {
                 .check();
 
         assertQuery("select salary, count(name) from person group by salary 
having salary < 10 order by salary")
+                .disableRules(rules)
                 .check();
 
         assertQuery("select count(name), name from person group by name")
+                .disableRules(rules)
                 .returns(1L, "Igor")
                 .returns(1L, "Ilya")
                 .returns(2L, "Roma")
@@ -127,43 +192,48 @@ public class ItAggregatesTest extends 
AbstractBasicIntegrationTest {
                 .check();
 
         assertQuery("select avg(salary) from person")
+                .disableRules(rules)
                 .returns(12.0)
                 .check();
 
         assertQuery("select name, salary from person where person.salary > 
(select avg(person.salary) from person)")
+                .disableRules(rules)
                 .returns(null, 15d)
                 .returns("Ilya", 15d)
                 .check();
 
         assertQuery("select avg(salary) from (select avg(salary) as salary 
from person union all select salary from person)")
+                .disableRules(rules)
                 .returns(12d)
                 .check();
     }
 
-    @Test
-    public void testMultipleRowsFromSingleAggr() {
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void testMultipleRowsFromSingleAggr(String[] rules) {
         assertThrows(
                 IgniteException.class,
-                () -> assertQuery("SELECT (SELECT name FROM person)").check()
+                () -> assertQuery("SELECT (SELECT name FROM 
person)").disableRules(rules).check()
         );
 
         assertThrows(
                 IgniteException.class,
-                () -> assertQuery("SELECT t.id, (SELECT x FROM 
TABLE(system_range(1, 5))) FROM person t").check()
+                () -> assertQuery("SELECT t.id, (SELECT x FROM 
TABLE(system_range(1, 5))) FROM person t").disableRules(rules).check()
         );
 
         assertThrows(
                 IgniteException.class,
                 () -> assertQuery("SELECT t.id, (SELECT x FROM "
-                        + "TABLE(system_range(t.id, t.id + 1))) FROM person 
t").check()
+                        + "TABLE(system_range(t.id, t.id + 1))) FROM person 
t").disableRules(rules).check()
         );
 
-        assertQuery("SELECT t.id, (SELECT x FROM TABLE(system_range(t.id, 
t.id))) FROM person t").check();
+        assertQuery("SELECT t.id, (SELECT x FROM TABLE(system_range(t.id, 
t.id))) FROM person t").disableRules(rules).check();
     }
 
-    @Test
-    public void testAnyValAggr() {
-        var res = sql("select any_value(name) from person");
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void testAnyValAggr(String[] rules) {
+        var res = sql(appendDisabledRules("select any_value(name) from 
person", rules));
 
         assertEquals(1, res.size());
 
@@ -172,7 +242,7 @@ public class ItAggregatesTest extends 
AbstractBasicIntegrationTest {
         assertTrue("Igor".equals(val) || "Roma".equals(val) || 
"Ilya".equals(val), "Unexpected value: " + val);
 
         // Test with grouping.
-        res = sql("select any_value(name), salary from person group by salary 
order by salary");
+        res = sql(appendDisabledRules("select any_value(name), salary from 
person group by salary order by salary", rules));
 
         assertEquals(2, res.size());
 
@@ -187,34 +257,77 @@ public class ItAggregatesTest extends 
AbstractBasicIntegrationTest {
 
     @Test
     public void testColocatedAggregate() {
-        sql("CREATE TABLE t1(id INT, val0 VARCHAR, val1 VARCHAR, val2 VARCHAR, 
PRIMARY KEY(id, val1)) "
-                + "COLOCATE BY (val1)");
-
-        sql("CREATE TABLE t2(id INT, val0 VARCHAR, val1 VARCHAR, val2 VARCHAR, 
PRIMARY KEY(id, val1)) "
-                + "COLOCATE BY (val1)");
-
-        for (int i = 0; i < 100; i++) {
-            sql("INSERT INTO t1 VALUES (?, ?, ?, ?)", i, "val" + i, "val" + i 
% 2, "val" + i);
+        try {
+            sql("CREATE TABLE t1(id INT, val0 VARCHAR, val1 VARCHAR, val2 
VARCHAR, PRIMARY KEY(id, val1)) "
+                    + "COLOCATE BY (val1)");
+
+            sql("CREATE TABLE t2(id INT, val0 VARCHAR, val1 VARCHAR, val2 
VARCHAR, PRIMARY KEY(id, val1)) "
+                    + "COLOCATE BY (val1)");
+
+            for (int i = 0; i < 100; i++) {
+                sql("INSERT INTO t1 VALUES (?, ?, ?, ?)", i, "val" + i, "val" 
+ i % 2, "val" + i);
+            }
+
+            sql("INSERT INTO t2 VALUES (0, 'val0', 'val0', 'val0'), (1, 
'val1', 'val1', 'val1')");
+
+            String sql = "SELECT val1, count(val2) FROM t1 GROUP BY val1";
+
+            assertQuery(sql)
+                    
.matches(QueryChecker.matches(".*Exchange.*Colocated.*Aggregate.*"))
+                    .returns("val0", 50L)
+                    .returns("val1", 50L)
+                    .check();
+
+            sql = "SELECT t2.val1, agg.cnt "
+                    + "FROM t2 JOIN (SELECT val1, COUNT(val2) AS cnt FROM t1 
GROUP BY val1) AS agg ON t2.val1 = agg.val1";
+
+            assertQuery(sql)
+                    
.matches(QueryChecker.matches(".*Exchange.*Join.*Colocated.*Aggregate.*"))
+                    .returns("val0", 50L)
+                    .returns("val1", 50L)
+                    .check();
+        } finally {
+            sql("DROP TABLE IF EXISTS t1");
+            sql("DROP TABLE IF EXISTS t2");
         }
+    }
 
-        sql("INSERT INTO t2 VALUES (0, 'val0', 'val0', 'val0'), (1, 'val1', 
'val1', 'val1')");
-
-        String sql = "SELECT val1, count(val2) FROM t1 GROUP BY val1";
-
-        assertQuery(sql)
-                
.matches(QueryChecker.matches(".*Exchange.*Colocated.*Aggregate.*"))
-                .returns("val0", 50L)
-                .returns("val1", 50L)
-                .check();
-
-        sql = "SELECT t2.val1, agg.cnt "
-                + "FROM t2 JOIN (SELECT val1, COUNT(val2) AS cnt FROM t1 GROUP 
BY val1) AS agg ON t2.val1 = agg.val1";
-
-        assertQuery(sql)
-                
.matches(QueryChecker.matches(".*Exchange.*Join.*Colocated.*Aggregate.*"))
-                .returns("val0", 50L)
-                .returns("val1", 50L)
-                .check();
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    public void testColocatedAggregate(String[] rules) {
+        try {
+            sql("CREATE TABLE t1(id INT, val0 VARCHAR, val1 VARCHAR, val2 
VARCHAR, PRIMARY KEY(id, val1)) "
+                    + "COLOCATE BY (val1)");
+
+            sql("CREATE TABLE t2(id INT, val0 VARCHAR, val1 VARCHAR, val2 
VARCHAR, PRIMARY KEY(id, val1)) "
+                    + "COLOCATE BY (val1)");
+
+            for (int i = 0; i < 100; i++) {
+                sql("INSERT INTO t1 VALUES (?, ?, ?, ?)", i, "val" + i, "val" 
+ i % 2, "val" + i);
+            }
+
+            sql("INSERT INTO t2 VALUES (0, 'val0', 'val0', 'val0'), (1, 
'val1', 'val1', 'val1')");
+
+            String sql = "SELECT val1, count(val2) FROM t1 GROUP BY val1";
+
+            assertQuery(sql)
+                    .disableRules(rules)
+                    .returns("val0", 50L)
+                    .returns("val1", 50L)
+                    .check();
+
+            sql = "SELECT t2.val1, agg.cnt "
+                    + "FROM t2 JOIN (SELECT val1, COUNT(val2) AS cnt FROM t1 
GROUP BY val1) AS agg ON t2.val1 = agg.val1";
+
+            assertQuery(sql)
+                    .disableRules(rules)
+                    .returns("val0", 50L)
+                    .returns("val1", 50L)
+                    .check();
+        } finally {
+            sql("DROP TABLE IF EXISTS t1");
+            sql("DROP TABLE IF EXISTS t2");
+        }
     }
 
     @Test
@@ -245,4 +358,148 @@ public class ItAggregatesTest extends 
AbstractBasicIntegrationTest {
                 .returns(null)
                 .check();
     }
+
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
+    public void testDifferentAgg(String[] rules) {
+        try {
+            sql("CREATE TABLE testMe (a INTEGER, b INTEGER, s VARCHAR);");
+            sql("INSERT INTO testMe VALUES (11, 1, 'hello'), (12, 2, 'world'), 
(11, 3, NULL)");
+            sql("INSERT INTO testMe VALUES (11, 3, 'hello'), (12, 2, 'world'), 
(10, 5, 'ahello'), (13, 6, 'world')");
+
+            assertQuery("SELECT DISTINCT(a) as a FROM testMe ORDER BY a")
+                    .disableRules(rules)
+                    .returns(10)
+                    .returns(11)
+                    .returns(12)
+                    .returns(13)
+                    .check();
+
+            assertQuery("SELECT COUNT(*) FROM testMe")
+                    .disableRules(rules)
+                    .returns(7L)
+                    .check();
+
+            // Such kind of queries can`t be processed with
+            if (Arrays.stream(rules).anyMatch(r -> 
r.contains("MapReduceSortAggregateConverterRule"))) {
+                assertQuery("SELECT COUNT(a), COUNT(DISTINCT(b)) FROM testMe")
+                        .disableRules(rules)
+                        .returns(7L, 5L)
+                        .check();
+            }
+
+            assertQuery("SELECT COUNT(a) as a, s FROM testMe GROUP BY s ORDER 
BY a, s")
+                    .disableRules(rules)
+                    .returns(1L, "ahello")
+                    .returns(1L, null)
+                    .returns(2L, "hello")
+                    .returns(3L, "world")
+                    .check();
+
+            assertQuery("SELECT COUNT(a) as a, AVG(a) as b, MIN(a), MIN(b), s 
FROM testMe GROUP BY s ORDER BY a, b")
+                    .disableRules(rules)
+                    .returns(1L, 10, 10, 5, "ahello")
+                    .returns(1L, 11, 11, 3, null)
+                    .returns(2L, 11, 11, 1, "hello")
+                    .returns(3L, 12, 12, 2, "world")
+                    .check();
+
+            assertQuery("SELECT COUNT(a) as a, AVG(a) as bb, MIN(a), MIN(b), s 
FROM testMe GROUP BY s, b ORDER BY a, s")
+                    .disableRules(rules)
+                    .returns(1L, 10, 10, 5, "ahello")
+                    .returns(1L, 11, 11, 1, "hello")
+                    .returns(1L, 11, 11, 3, "hello")
+                    .returns(1L, 13, 13, 6, "world")
+                    .returns(1L, 11, 11, 3, null)
+                    .returns(2L, 12, 12, 2, "world")
+                    .check();
+
+            assertQuery("SELECT COUNT(a) FROM testMe")
+                    .disableRules(rules)
+                    .returns(7L)
+                    .check();
+
+            assertQuery("SELECT COUNT(DISTINCT(a)) FROM testMe")
+                    .disableRules(rules)
+                    .returns(4L)
+                    .check();
+
+            assertQuery("SELECT COUNT(a), COUNT(s), COUNT(*) FROM testMe")
+                    .disableRules(rules)
+                    .returns(7L, 6L, 7L)
+                    .check();
+
+            assertQuery("SELECT AVG(a) FROM testMe")
+                    .disableRules(rules)
+                    .returns(11)
+                    .check();
+
+            assertQuery("SELECT MIN(a) FROM testMe")
+                    .disableRules(rules)
+                    .returns(10)
+                    .check();
+
+            assertQuery("SELECT COUNT(a), COUNT(DISTINCT(a)) FROM testMe")
+                    .disableRules(rules)
+                    .returns(7L, 4L)
+                    .check();
+
+            assertQuery("SELECT COUNT(a), COUNT(DISTINCT a), SUM(a), 
SUM(DISTINCT a) FROM testMe")
+                    .disableRules(rules)
+                    .returns(7L, 4L, 80L, 46L)
+                    .check();
+        } finally {
+            sql("DROP TABLE IF EXISTS testMe");
+        }
+    }
+
+    @ParameterizedTest
+    @MethodSource("provideRules")
+    @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
+    public void checkEmptyTable(String[] rules) {
+        sql("CREATE TABLE t (a INTEGER, b INTEGER)");
+
+        try {
+            assertQuery("SELECT min(b) FROM t GROUP BY a")
+                    .disableRules(rules)
+                    .returnNothing().check();
+        } finally {
+            sql("DROP TABLE t");
+        }
+    }
+
+    static String[][] makePermutations(String[] rules) {
+        String[][] out = new String[rules.length][rules.length - 1];
+
+        for (int i = 0; i < disabledRules.length; ++i) {
+            int pos = 0;
+            for (int ruleIdx = 0; ruleIdx < disabledRules.length; ++ruleIdx) {
+                if (ruleIdx == i) {
+                    continue;
+                }
+                out[i][pos++] = disabledRules[ruleIdx];
+            }
+        }
+
+        return out;
+    }
+
+    private static Stream<Arguments> provideRules() {
+        return Arrays.stream(makePermutations(disabledRules)).map(k -> 
Arguments.of((Object) k));
+    }
+
+    private String appendDisabledRules(String sql, String[] rules) {
+        sql = sql.toLowerCase(Locale.ENGLISH);
+        int pos = sql.indexOf("select");
+
+        assert pos >= 0;
+
+        String newSql = sql.substring(0, pos + "select".length() + 1);
+        newSql += " /*+ DISABLE_RULE( '";
+        newSql += String.join("' ,'", rules);
+        newSql += "') */ ";
+        newSql += sql.substring(pos + "select".length() + 1);
+        return newSql;
+    }
 }
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSortAggregateTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSortAggregateTest.java
deleted file mode 100644
index eaafb69e1d..0000000000
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItSortAggregateTest.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.sql.engine;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.List;
-import java.util.Locale;
-import org.apache.ignite.internal.testframework.WithSystemProperty;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-/**
- * Sort aggregate integration test.
- */
-public class ItSortAggregateTest extends AbstractBasicIntegrationTest {
-    private static final int ROWS = 103;
-
-    /**
-     * Before all.
-     */
-    @BeforeAll
-    static void initTestData() throws InterruptedException {
-        sql("CREATE TABLE test (id INT PRIMARY KEY, grp0 INT, grp1 INT, val0 
INT, val1 INT) WITH replicas=2,partitions=10");
-        sql("CREATE TABLE test_one_col_idx (pk INT PRIMARY KEY, col0 INT)");
-
-        sql("CREATE INDEX test_idx ON test(grp0, grp1)");
-        sql("CREATE INDEX test_one_col_idx_idx ON test_one_col_idx(col0)");
-
-        // FIXME: https://issues.apache.org/jira/browse/IGNITE-18203
-        waitForIndex("test_idx");
-        waitForIndex("test_one_col_idx_idx");
-
-        for (int i = 0; i < ROWS; i++) {
-            sql("INSERT INTO test (id, grp0, grp1, val0, val1) VALUES (?, ?, 
?, ?, ?)", i, i / 10, i / 100, 1, 2);
-            sql("INSERT INTO test_one_col_idx (pk, col0) VALUES (?, ?)", i, i);
-        }
-    }
-
-    @Test
-    public void mapReduceAggregate() {
-        String disabledRules = " /*+ 
DISABLE_RULE('MapReduceHashAggregateConverterRule', 
'ColocatedHashAggregateConverterRule', "
-                + "'ColocatedSortAggregateConverterRule') */ ";
-
-        var res = sql(
-                appendDisabledRules("SELECT SUM(val0), SUM(val1), grp0 FROM 
TEST GROUP BY grp0 HAVING SUM(val1) > 10", disabledRules));
-
-        assertEquals(ROWS / 10, res.size());
-
-        res.forEach(r -> {
-            long s0 = (Long) r.get(0);
-            long s1 = (Long) r.get(1);
-
-            assertEquals(s0 * 2, s1);
-        });
-    }
-
-    @Test
-    public void correctCollationsOnMapReduceSortAgg() {
-        String disabledRules = " /*+ 
DISABLE_RULE('MapReduceHashAggregateConverterRule', 
'ColocatedHashAggregateConverterRule', "
-                + "'ColocatedSortAggregateConverterRule') */ ";
-
-        var cursors = sql(
-                appendDisabledRules("SELECT PK FROM TEST_ONE_COL_IDX WHERE 
col0 IN (SELECT col0 FROM TEST_ONE_COL_IDX)", disabledRules));
-
-        assertEquals(ROWS, cursors.size());
-    }
-
-    @Test
-    @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
-    public void testDifferentCollocatedSortAgg() {
-        try {
-            sql("CREATE TABLE testMe (a INTEGER, b INTEGER, s VARCHAR);");
-            sql("INSERT INTO testMe VALUES (11, 1, 'hello'), (12, 2, 'world'), 
(11, 3, NULL)");
-            sql("INSERT INTO testMe VALUES (11, 3, 'hello'), (12, 2, 'world'), 
(10, 5, 'ahello'), (13, 6, 'world')");
-
-            String[] disabledRules = {"MapReduceHashAggregateConverterRule", 
"MapReduceSortAggregateConverterRule",
-                    "ColocatedHashAggregateConverterRule"};
-
-            assertQuery("SELECT DISTINCT(a) as a FROM testMe ORDER BY a")
-                    .disableRules(disabledRules)
-                    .returns(10)
-                    .returns(11)
-                    .returns(12)
-                    .returns(13)
-                    .check();
-
-            assertQuery("SELECT COUNT(*) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(7L)
-                    .check();
-
-            assertQuery("SELECT COUNT(a), COUNT(DISTINCT(b)) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(7L, 5L)
-                    .check();
-
-            assertQuery("SELECT COUNT(a) as a, s FROM testMe GROUP BY s ORDER 
BY a, s")
-                    .disableRules(disabledRules)
-                    .returns(1L, "ahello")
-                    .returns(1L, null)
-                    .returns(2L, "hello")
-                    .returns(3L, "world")
-                    .check();
-
-            assertQuery("SELECT COUNT(a) as a, AVG(a) as b, MIN(a), MIN(b), s 
FROM testMe GROUP BY s ORDER BY a, b")
-                    .disableRules(disabledRules)
-                    .returns(1L, 10, 10, 5, "ahello")
-                    .returns(1L, 11, 11, 3, null)
-                    .returns(2L, 11, 11, 1, "hello")
-                    .returns(3L, 12, 12, 2, "world")
-                    .check();
-
-            assertQuery("SELECT COUNT(a) as a, AVG(a) as bb, MIN(a), MIN(b), s 
FROM testMe GROUP BY s, b ORDER BY a, s")
-                    .disableRules(disabledRules)
-                    .returns(1L, 10, 10, 5, "ahello")
-                    .returns(1L, 11, 11, 1, "hello")
-                    .returns(1L, 11, 11, 3, "hello")
-                    .returns(1L, 13, 13, 6, "world")
-                    .returns(1L, 11, 11, 3, null)
-                    .returns(2L, 12, 12, 2, "world")
-                    .check();
-
-            assertQuery("SELECT COUNT(a) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(7L)
-                    .check();
-
-            assertQuery("SELECT COUNT(DISTINCT(a)) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(4L)
-                    .check();
-
-            assertQuery("SELECT COUNT(a), COUNT(s), COUNT(*) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(7L, 6L, 7L)
-                    .check();
-
-            assertQuery("SELECT AVG(a) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(11)
-                    .check();
-
-            assertQuery("SELECT MIN(a) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(10)
-                    .check();
-
-            assertQuery("SELECT COUNT(a), COUNT(DISTINCT(a)) FROM testMe")
-                    .disableRules(disabledRules)
-                    .returns(7L, 4L)
-                    .check();
-        } finally {
-            sql("DROP TABLE testMe");
-        }
-    }
-
-    @WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
-    @Test
-    public void checkEmptyTable() {
-        sql("CREATE TABLE t (a INTEGER, b INTEGER)");
-
-        // Check ColocatedSortAggregate
-        String[] disabledRules1 = {"MapReduceHashAggregateConverterRule", 
"MapReduceSortAggregateConverterRule",
-                "ColocatedHashAggregateConverterRule"};
-
-        // Check MapReduceSortAggregate
-        String[] disabledRules2 = {"MapReduceHashAggregateConverterRule", 
"ColocatedSortAggregateConverterRule",
-                "ColocatedHashAggregateConverterRule"};
-
-        try {
-            for (String[] disabledRules : List.of(disabledRules1, 
disabledRules2)) {
-                assertQuery("SELECT min(b) FROM t GROUP BY a")
-                        .disableRules(disabledRules)
-                        .returnNothing().check();
-            }
-        } finally {
-            sql("DROP TABLE t");
-        }
-    }
-
-    private String appendDisabledRules(String sql, String rules) {
-        sql = sql.toLowerCase(Locale.ENGLISH);
-        int pos = sql.indexOf("select");
-
-        assert pos >= 0;
-
-        String newSql = sql.substring(0, pos + "select".length() + 1);
-        newSql += rules;
-        newSql += sql.substring(pos + "select".length() + 1);
-        return newSql;
-    }
-}
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
index e60e6b8fc7..5cb79e1cce 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/LogicalRelImplementor.java
@@ -712,13 +712,19 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
 
         RowFactory<RowT> rowFactory = 
ctx.rowHandler().factory(ctx.getTypeFactory(), rowType);
 
+        Comparator<RowT> comp = expressionFactory.comparator(rel.collation());
+
+        if (rel.getGroupSet().isEmpty() && comp == null) {
+            comp = (k1, k2) -> 0;
+        }
+
         SortAggregateNode<RowT> node = new SortAggregateNode<>(
                 ctx,
                 type,
                 rel.getGroupSet(),
                 accFactory,
                 rowFactory,
-                expressionFactory.comparator(rel.collation())
+                comp
         );
 
         Node<RowT> input = visit(rel.getInput());
@@ -743,13 +749,19 @@ public class LogicalRelImplementor<RowT> implements 
IgniteRelVisitor<Node<RowT>>
 
         RowFactory<RowT> rowFactory = 
ctx.rowHandler().factory(ctx.getTypeFactory(), rowType);
 
+        Comparator<RowT> comp = expressionFactory.comparator(rel.collation());
+
+        if (rel.getGroupSet().isEmpty() && comp == null) {
+            comp = (k1, k2) -> 0;
+        }
+
         SortAggregateNode<RowT> node = new SortAggregateNode<>(
                 ctx,
                 type,
                 rel.getGroupSet(),
                 accFactory,
                 rowFactory,
-                expressionFactory.comparator(rel.collation())
+                comp
         );
 
         Node<RowT> input = visit(rel.getInput());
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/SortAggregateNode.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/SortAggregateNode.java
index 6b6de6f43e..4b88ae6c3d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/SortAggregateNode.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/SortAggregateNode.java
@@ -66,7 +66,13 @@ public class SortAggregateNode<RowT> extends 
AbstractNode<RowT> implements Singl
 
     /**
      * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     *
+     * @param ctx Execution context.
+     * @param type Aggregation operation (phase) type.
+     * @param grpSet Bit set of grouping fields.
+     * @param accFactory Accumulators.
+     * @param rowFactory Row factory.
+     * @param comp Comparator.
      */
     public SortAggregateNode(
             ExecutionContext<RowT> ctx,
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/ColocationGroup.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/ColocationGroup.java
index 21f8f08bfb..4b153cffab 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/ColocationGroup.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/ColocationGroup.java
@@ -198,7 +198,7 @@ public class ColocationGroup implements Serializable {
      * Constructor.
      * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
      */
-    public ColocationGroup finalaze() {
+    public ColocationGroup complete() {
         if (assignments == null && nodeNames == null) {
             return this;
         }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/FragmentMapping.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/FragmentMapping.java
index 6951bb0fe7..c564c67fd9 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/FragmentMapping.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/metadata/FragmentMapping.java
@@ -156,7 +156,7 @@ public class FragmentMapping implements Serializable {
 
         List<ColocationGroup> colocationGroups = this.colocationGroups;
 
-        colocationGroups = Commons.transform(colocationGroups, 
ColocationGroup::finalaze);
+        colocationGroups = Commons.transform(colocationGroups, 
ColocationGroup::complete);
 
         List<String> nodes = nodeNames();
         List<String> nodes0 = nodes.isEmpty() ? nodesSource.get() : nodes;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteHashIndexSpool.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteHashIndexSpool.java
index 945194154c..fc26b0b005 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteHashIndexSpool.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteHashIndexSpool.java
@@ -38,7 +38,7 @@ import org.apache.ignite.internal.sql.engine.util.RexUtils;
 /**
  * Relational operator that returns the hashed contents of a table and allow 
to lookup rows by specified keys.
  */
-public class IgniteHashIndexSpool extends AbstractIgniteSpool implements 
InternalIgniteRel {
+public class IgniteHashIndexSpool extends AbstractIgniteSpool {
     /** Search row. */
     private final List<RexNode> searchRow;
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedAggregateBase.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedAggregateBase.java
index 4835796e66..78a50351e6 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedAggregateBase.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedAggregateBase.java
@@ -40,7 +40,7 @@ import org.apache.ignite.internal.sql.engine.util.Commons;
  */
 public abstract class IgniteColocatedAggregateBase extends IgniteAggregate 
implements TraitsAwareIgniteRel {
     /** {@inheritDoc} */
-    protected IgniteColocatedAggregateBase(
+    IgniteColocatedAggregateBase(
             RelOptCluster cluster,
             RelTraitSet traitSet,
             RelNode input,
@@ -51,8 +51,12 @@ public abstract class IgniteColocatedAggregateBase extends 
IgniteAggregate imple
         super(cluster, traitSet, input, groupSet, groupSets, aggCalls);
     }
 
-    /** {@inheritDoc} */
-    protected IgniteColocatedAggregateBase(RelInput input) {
+    /**
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
+     */
+    IgniteColocatedAggregateBase(RelInput input) {
         super(TraitUtils.changeTraits(input, IgniteConvention.INSTANCE));
     }
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedHashAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedHashAggregate.java
index b6386893b8..6ac3795c90 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedHashAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedHashAggregate.java
@@ -41,6 +41,11 @@ public class IgniteColocatedHashAggregate extends 
IgniteColocatedAggregateBase i
         super(cluster, traitSet, input, groupSet, groupSets, aggCalls);
     }
 
+    /**
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
+     */
     public IgniteColocatedHashAggregate(RelInput input) {
         super(input);
     }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedSortAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedSortAggregate.java
index 6c71a11d11..a39e382dc6 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedSortAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteColocatedSortAggregate.java
@@ -61,8 +61,9 @@ public class IgniteColocatedSortAggregate extends 
IgniteColocatedAggregateBase i
     }
 
     /**
-     * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
      */
     public IgniteColocatedSortAggregate(RelInput input) {
         super(input);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapAggregateBase.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapAggregateBase.java
index fa8526dd4c..2fbd3d836d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapAggregateBase.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapAggregateBase.java
@@ -53,17 +53,6 @@ public abstract class IgniteMapAggregateBase extends 
IgniteAggregate implements
         super(TraitUtils.changeTraits(input, IgniteConvention.INSTANCE));
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public Pair<RelTraitSet, List<RelTraitSet>> 
passThroughDistribution(RelTraitSet nodeTraits,
-            List<RelTraitSet> inTraits) {
-        if 
(TraitUtils.distribution(nodeTraits).satisfies(IgniteDistributions.single())) {
-            return null;
-        } else {
-            return 
TraitsAwareIgniteRel.super.passThroughDistribution(nodeTraits, inTraits);
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public List<Pair<RelTraitSet, List<RelTraitSet>>> deriveRewindability(
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapHashAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapHashAggregate.java
index bc31dd4ef0..51d9314c8d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapHashAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapHashAggregate.java
@@ -58,8 +58,9 @@ public class IgniteMapHashAggregate extends 
IgniteMapAggregateBase implements Ig
     }
 
     /**
-     * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
      */
     public IgniteMapHashAggregate(RelInput input) {
         super(input);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapSortAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapSortAggregate.java
index cf3ab3ac57..b6c4ad4fd4 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapSortAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteMapSortAggregate.java
@@ -64,14 +64,14 @@ public class IgniteMapSortAggregate extends 
IgniteMapAggregateBase implements Ig
         super(cluster, traitSet, input, groupSet, groupSets, aggCalls);
 
         assert Objects.nonNull(collation);
-        assert !collation.isDefault();
 
         this.collation = collation;
     }
 
     /**
-     * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
      */
     public IgniteMapSortAggregate(RelInput input) {
         super(TraitUtils.changeTraits(input, IgniteConvention.INSTANCE));
@@ -79,7 +79,6 @@ public class IgniteMapSortAggregate extends 
IgniteMapAggregateBase implements Ig
         collation = input.getCollation();
 
         assert Objects.nonNull(collation);
-        assert !collation.isDefault();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceAggregateBase.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceAggregateBase.java
index 334630eb96..f806b6eadb 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceAggregateBase.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceAggregateBase.java
@@ -77,8 +77,9 @@ public abstract class IgniteReduceAggregateBase extends 
SingleRel implements Tra
     }
 
     /**
-     * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
      */
     protected IgniteReduceAggregateBase(RelInput input) {
         this(
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceHashAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceHashAggregate.java
index 712e81042b..6ce52bf1eb 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceHashAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceHashAggregate.java
@@ -62,8 +62,9 @@ public class IgniteReduceHashAggregate extends 
IgniteReduceAggregateBase impleme
     }
 
     /**
-     * Constructor.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Constructor used for deserialization.
+     *
+     * @param input Serialized representation.
      */
     public IgniteReduceHashAggregate(RelInput input) {
         super(input);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceSortAggregate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceSortAggregate.java
index da3df59faf..cf60c766c1 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceSortAggregate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteReduceSortAggregate.java
@@ -62,7 +62,6 @@ public class IgniteReduceSortAggregate extends 
IgniteReduceAggregateBase impleme
         super(cluster, traits, input, groupSet, groupSets, aggCalls, rowType);
 
         assert Objects.nonNull(collation);
-        assert !collation.isDefault();
 
         this.collation = collation;
     }
@@ -77,7 +76,6 @@ public class IgniteReduceSortAggregate extends 
IgniteReduceAggregateBase impleme
         collation = input.getCollation();
 
         assert Objects.nonNull(collation);
-        assert !collation.isDefault();
     }
 
     /** {@inheritDoc} */
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortAggregateConverterRule.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortAggregateConverterRule.java
index ce88baaa0e..aa1ec3e062 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortAggregateConverterRule.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rule/SortAggregateConverterRule.java
@@ -96,10 +96,8 @@ public class SortAggregateConverterRule {
 
         /** {@inheritDoc} */
         @Override
-        protected PhysicalNode convert(RelOptPlanner planner, RelMetadataQuery 
mq,
-                LogicalAggregate agg) {
-            // Applicable only for GROUP BY or SELECT DISTINCT
-            if (nullOrEmpty(agg.getGroupSet()) || agg.getGroupSets().size() > 
1) {
+        protected @Nullable PhysicalNode convert(RelOptPlanner planner, 
RelMetadataQuery mq, LogicalAggregate agg) {
+            if ((nullOrEmpty(agg.getGroupSet()) && 
agg.getGroupSets().isEmpty()) || agg.getGroupSets().size() > 1) {
                 return null;
             }
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AggregatePlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AggregatePlannerTest.java
index 885246fb9f..0c882f1c4d 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AggregatePlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AggregatePlannerTest.java
@@ -189,7 +189,7 @@ public class AggregatePlannerTest extends 
AbstractAggregatePlannerTest {
     }
 
     /**
-     * Test that aggregate has single distribution output even if parent node 
accept random distibution inputs.
+     * Test that aggregate has single distribution output even if parent node 
accept random distribution inputs.
      *
      * @throws Exception If failed.
      */
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/HashAggregatePlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/HashAggregatePlannerTest.java
index bf4b8be044..51b86e455c 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/HashAggregatePlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/HashAggregatePlannerTest.java
@@ -63,7 +63,8 @@ public class HashAggregatePlannerTest extends 
AbstractAggregatePlannerTest {
                 IgniteDistributions.affinity(0, UUID.randomUUID(), 
DEFAULT_ZONE_ID)
         );
 
-        String sql = "SELECT * FROM emps WHERE emps.salary = (SELECT 
AVG(emps.salary) FROM emps)";
+        String sql = "SELECT /*+ 
DISABLE_RULE('MapReduceSortAggregateConverterRule', 
'ColocatedHashAggregateConverterRule', "
+                + "'ColocatedSortAggregateConverterRule') */ * FROM emps WHERE 
emps.salary = (SELECT AVG(emps.salary) FROM emps)";
 
         IgniteRel phys = physicalPlan(
                 sql,
@@ -101,7 +102,8 @@ public class HashAggregatePlannerTest extends 
AbstractAggregatePlannerTest {
 
         publicSchema.addTable(tbl);
 
-        String sqlCount = "SELECT COUNT(*) FROM test";
+        String sqlCount = "SELECT /*+ 
DISABLE_RULE('MapReduceSortAggregateConverterRule', 
'ColocatedHashAggregateConverterRule', "
+                + "'ColocatedSortAggregateConverterRule') */ COUNT(*) FROM 
test";
 
         IgniteRel phys = physicalPlan(
                 sqlCount,

Reply via email to