You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by zs...@apache.org on 2022/02/01 16:13:44 UTC
[ignite-3] branch main updated: IGNITE-16328 Sql Adopt IGNITE-15992, IGNITE-16138 - Fixes #565.
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 3ad271c IGNITE-16328 Sql Adopt IGNITE-15992, IGNITE-16138 - Fixes #565.
3ad271c is described below
commit 3ad271cc58225703ef408db319582f350453e06d
Author: zstan <st...@gmail.com>
AuthorDate: Tue Feb 1 19:12:57 2022 +0300
IGNITE-16328 Sql Adopt IGNITE-15992, IGNITE-16138 - Fixes #565.
Correlated queries with ORDER and LIMIT can't be planned.
AssertionError: Input not sorted for some ORDER BY containing requests.
Signed-off-by: zstan <st...@gmail.com>
---
.../internal/sql/engine/ItSortAggregateTest.java | 34 +++++++++++++
.../internal/sql/engine/util/QueryChecker.java | 18 +++----
.../ignite/internal/sql/engine/exec/rel/Inbox.java | 55 ++++++++++++++--------
.../sql/engine/exec/rel/SortAggregateNode.java | 6 +--
.../sql/engine/prepare/ddl/CreateIndexCommand.java | 2 +-
.../internal/sql/engine/rel/IgniteIndexScan.java | 10 ++--
.../internal/sql/engine/rel/IgniteLimit.java | 8 +++-
.../internal/sql/engine/rel/IgniteTableScan.java | 12 ++---
.../engine/rel/agg/IgniteSortAggregateBase.java | 16 +++++--
.../engine/rel/logical/IgniteLogicalTableScan.java | 6 +--
.../engine/planner/SortAggregatePlannerTest.java | 41 ++++++++++++++++
11 files changed, 154 insertions(+), 54 deletions(-)
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
index 233ad60..4ac7024 100644
--- 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
@@ -60,12 +60,29 @@ public class ItSortAggregateTest extends AbstractBasicIntegrationTest {
)
.build();
+ TableDefinition schTbl2 = SchemaBuilders.tableBuilder("PUBLIC", "TEST_ONE_COL_IDX")
+ .columns(
+ SchemaBuilders.column("PK", ColumnType.INT32).build(),
+ SchemaBuilders.column("COL0", ColumnType.INT32).asNullable(true).build()
+ )
+ .withPrimaryKey("PK")
+ .withIndex(
+ SchemaBuilders.sortedIndex("IDX")
+ .addIndexColumn("COL0").desc().done()
+ .build()
+ )
+ .build();
+
Table table = CLUSTER_NODES.get(0).tables().createTable(schTbl1.canonicalName(), tblCh ->
SchemaConfigurationConverter.convert(schTbl1, tblCh)
.changeReplicas(2)
.changePartitions(10)
);
+ Table tblOneColIdx = CLUSTER_NODES.get(0).tables().createTable(schTbl2.canonicalName(), tblCh ->
+ SchemaConfigurationConverter.convert(schTbl2, tblCh)
+ );
+
RecordView<Tuple> view = table.recordView();
for (int i = 0; i < ROWS; i++) {
view.insert(
@@ -78,6 +95,16 @@ public class ItSortAggregateTest extends AbstractBasicIntegrationTest {
.set("VAL1", 2)
);
}
+
+ RecordView<Tuple> view1 = tblOneColIdx.recordView();
+ for (int i = 0; i < ROWS; i++) {
+ view1.insert(
+ null,
+ Tuple.create()
+ .set("PK", i)
+ .set("COL0", i)
+ );
+ }
}
@Test
@@ -98,4 +125,11 @@ public class ItSortAggregateTest extends AbstractBasicIntegrationTest {
assertEquals(s0 * 2, (int) s1);
});
}
+
+ @Test
+ public void correctCollationsOnMapReduceSortAgg() {
+ List<List<?>> cursors = sql("SELECT PK FROM TEST_ONE_COL_IDX WHERE col0 IN (SELECT col0 FROM TEST_ONE_COL_IDX)");
+
+ assertEquals(ROWS, cursors.size());
+ }
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
index 54c5cf6..cbf0650 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
@@ -95,14 +95,14 @@ public abstract class QueryChecker {
*/
public static Matcher<String> notContainsProject(String schema, String tblName) {
return CoreMatchers.not(containsSubPlan("Scan(table=[[" + schema + ", "
- + tblName + "]], " + "requiredColunms="));
+ + tblName + "]], " + "requiredColumns="));
}
/**
* {@link #containsProject(String, String, int...)} reverter.
*/
- public static Matcher<String> notContainsProject(String schema, String tblName, int... requiredColunms) {
- return CoreMatchers.not(containsProject(schema, tblName, requiredColunms));
+ public static Matcher<String> notContainsProject(String schema, String tblName, int... requiredColumns) {
+ return CoreMatchers.not(containsProject(schema, tblName, requiredColumns));
}
/**
@@ -110,13 +110,13 @@ public abstract class QueryChecker {
*
* @param schema Schema name.
* @param tblName Table name.
- * @param requiredColunms columns in projection.
+ * @param requiredColumns columns in projection.
* @return Matcher.
*/
- public static Matcher<String> containsProject(String schema, String tblName, int... requiredColunms) {
+ public static Matcher<String> containsProject(String schema, String tblName, int... requiredColumns) {
Matcher<String> res = matches(".*Ignite(Table|Index)Scan\\(table=\\[\\[" + schema + ", "
+ tblName + "\\]\\], " + ".*requiredColumns=\\[\\{"
- + Arrays.toString(requiredColunms)
+ + Arrays.toString(requiredColumns)
.replaceAll("\\[", "")
.replaceAll("]", "") + "\\}\\].*");
return res;
@@ -127,13 +127,13 @@ public abstract class QueryChecker {
*
* @param schema Schema name.
* @param tblName Table name.
- * @param requiredColunms columns in projection.
+ * @param requiredColumns columns in projection.
* @return Matcher.
*/
- public static Matcher<String> containsOneProject(String schema, String tblName, int... requiredColunms) {
+ public static Matcher<String> containsOneProject(String schema, String tblName, int... requiredColumns) {
return matchesOnce(".*Ignite(Table|Index)Scan\\(table=\\[\\[" + schema + ", "
+ tblName + "\\]\\], " + ".*requiredColumns=\\[\\{"
- + Arrays.toString(requiredColunms)
+ + Arrays.toString(requiredColumns)
.replaceAll("\\[", "")
.replaceAll("]", "") + "\\}\\].*");
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
index 1ff72d8..27d1434 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/rel/Inbox.java
@@ -17,6 +17,8 @@
package org.apache.ignite.internal.sql.engine.exec.rel;
+import static org.apache.calcite.util.Util.unexpected;
+
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
@@ -204,29 +206,43 @@ public class Inbox<RowT> extends AbstractNode<RowT> implements Mailbox<RowT>, Si
}
}
- private void pushOrdered() throws Exception {
- PriorityQueue<Pair<RowT, Buffer>> heap =
- new PriorityQueue<>(Math.max(buffers.size(), 1), Map.Entry.comparingByKey(comp));
-
- Iterator<Buffer> it = buffers.iterator();
-
+ /** Checks that all corresponding buffers are in ready state. */
+ private boolean checkAllBuffsReady(Iterator<Buffer> it) {
while (it.hasNext()) {
Buffer buf = it.next();
- switch (buf.check()) {
- case END:
- it.remove();
+ State state = buf.check();
- break;
+ switch (state) {
case READY:
- heap.offer(Pair.of(buf.peek(), buf));
-
+ break;
+ case END:
+ it.remove();
break;
case WAITING:
-
- return;
+ return false;
default:
- break;
+ throw unexpected(state);
+ }
+ }
+ return true;
+ }
+
+ private void pushOrdered() throws Exception {
+ if (!checkAllBuffsReady(buffers.iterator())) {
+ return;
+ }
+
+ PriorityQueue<Pair<RowT, Buffer>> heap =
+ new PriorityQueue<>(Math.max(buffers.size(), 1), Map.Entry.comparingByKey(comp));
+
+ for (Buffer buf : buffers) {
+ State state = buf.check();
+
+ if (state == State.READY) {
+ heap.offer(Pair.of(buf.peek(), buf));
+ } else {
+ throw new AssertionError("Unexpected buffer state: " + state);
}
}
@@ -240,20 +256,19 @@ public class Inbox<RowT> extends AbstractNode<RowT> implements Mailbox<RowT>, Si
requested--;
downstream().push(buf.remove());
- switch (buf.check()) {
+ State state = buf.check();
+
+ switch (state) {
case END:
buffers.remove(buf);
-
break;
case READY:
heap.offer(Pair.of(buf.peek(), buf));
-
break;
case WAITING:
-
return;
default:
- break;
+ throw unexpected(state);
}
}
} finally {
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 81899d8..593845f 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
@@ -226,16 +226,12 @@ public class SortAggregateNode<RowT> extends AbstractNode<RowT> implements Singl
private class Group {
private final List<AccumulatorWrapper<RowT>> accumWrps;
- private final RowHandler<RowT> handler;
-
private final Object[] grpKeys;
private Group(Object[] grpKeys) {
this.grpKeys = grpKeys;
accumWrps = hasAccumulators() ? accFactory.get() : Collections.emptyList();
-
- handler = context().rowHandler();
}
private void add(RowT row) {
@@ -261,6 +257,8 @@ public class SortAggregateNode<RowT> extends AbstractNode<RowT> implements Singl
}
private void addOnReducer(RowT row) {
+ RowHandler<RowT> handler = context().rowHandler();
+
List<Accumulator> accums = hasAccumulators()
? (List<Accumulator>) handler.get(handler.columnCount(row) - 1, row) : Collections.emptyList();
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateIndexCommand.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateIndexCommand.java
index 1e60c08..3cb6e0b 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateIndexCommand.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateIndexCommand.java
@@ -39,7 +39,7 @@ public class CreateIndexCommand implements DdlCommand {
/** Quietly ignore this command if index already exists. */
private boolean ifIdxNotExists;
- /** Colunms covered with ordering. */
+ /** Columns covered with ordering. */
List<Pair<String, Boolean>> cols;
/** Return idx name. */
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
index e07d53d..26c41cf 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteIndexScan.java
@@ -31,7 +31,7 @@ import org.apache.ignite.internal.sql.engine.util.IndexConditions;
import org.jetbrains.annotations.Nullable;
/**
- * Relational operator that returns the contents of a table.
+ * Relational operator that returns the contents of a table using an index.
*/
public class IgniteIndexScan extends AbstractIndexScan implements SourceAwareIgniteRel {
private final long sourceId;
@@ -53,7 +53,7 @@ public class IgniteIndexScan extends AbstractIndexScan implements SourceAwareIgn
}
/**
- * Creates a TableScan.
+ * Creates a IndexScan.
*
* @param cluster Cluster that this relational expression belongs to
* @param traits Traits of this relational expression
@@ -69,7 +69,7 @@ public class IgniteIndexScan extends AbstractIndexScan implements SourceAwareIgn
}
/**
- * Creates a TableScan.
+ * Creates a IndexScan.
*
* @param cluster Cluster that this relational expression belongs to
* @param traits Traits of this relational expression
@@ -93,7 +93,7 @@ public class IgniteIndexScan extends AbstractIndexScan implements SourceAwareIgn
}
/**
- * Creates a TableScan.
+ * Creates a IndexScan.
*
* @param cluster Cluster that this relational expression belongs to
* @param traits Traits of this relational expression
@@ -101,7 +101,7 @@ public class IgniteIndexScan extends AbstractIndexScan implements SourceAwareIgn
* @param idxName Index name.
* @param proj Projects.
* @param cond Filters.
- * @param requiredCols Participating colunms.
+ * @param requiredCols Participating columns.
*/
private IgniteIndexScan(
long sourceId,
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteLimit.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteLimit.java
index f683460..6b0074b 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteLimit.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteLimit.java
@@ -22,6 +22,7 @@ import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelInput;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelWriter;
@@ -120,7 +121,12 @@ public class IgniteLimit extends SingleRel implements InternalIgniteRel {
return null;
}
- if (!TraitUtils.collation(required).satisfies(TraitUtils.collation(traitSet))) {
+ RelCollation requiredCollation = TraitUtils.collation(required);
+ RelCollation relCollation = TraitUtils.collation(traitSet);
+
+ if (relCollation.satisfies(requiredCollation)) {
+ required = required.replace(relCollation);
+ } else if (!requiredCollation.satisfies(relCollation)) {
return null;
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
index 25aca95..50eced2 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/IgniteTableScan.java
@@ -74,7 +74,7 @@ public class IgniteTableScan extends ProjectableFilterableTableScan implements S
* @param tbl Table definition.
* @param proj Projects.
* @param cond Filters.
- * @param requiredColunms Participating colunms.
+ * @param requiredColumns Participating columns.
*/
public IgniteTableScan(
RelOptCluster cluster,
@@ -82,9 +82,9 @@ public class IgniteTableScan extends ProjectableFilterableTableScan implements S
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
- @Nullable ImmutableBitSet requiredColunms
+ @Nullable ImmutableBitSet requiredColumns
) {
- this(-1L, cluster, traits, tbl, proj, cond, requiredColunms);
+ this(-1L, cluster, traits, tbl, proj, cond, requiredColumns);
}
/**
@@ -95,7 +95,7 @@ public class IgniteTableScan extends ProjectableFilterableTableScan implements S
* @param tbl Table definition.
* @param proj Projects.
* @param cond Filters.
- * @param requiredColunms Participating colunms.
+ * @param requiredColumns Participating columns.
*/
public IgniteTableScan(
long sourceId,
@@ -104,9 +104,9 @@ public class IgniteTableScan extends ProjectableFilterableTableScan implements S
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
- @Nullable ImmutableBitSet requiredColunms
+ @Nullable ImmutableBitSet requiredColumns
) {
- super(cluster, traits, List.of(), tbl, proj, cond, requiredColunms);
+ super(cluster, traits, List.of(), tbl, proj, cond, requiredColumns);
this.sourceId = sourceId;
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteSortAggregateBase.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteSortAggregateBase.java
index cc54ce4..772cf61 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteSortAggregateBase.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/agg/IgniteSortAggregateBase.java
@@ -19,11 +19,14 @@ package org.apache.ignite.internal.sql.engine.rel.agg;
import static org.apache.ignite.internal.sql.engine.util.Commons.maxPrefix;
+import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
+import java.util.stream.Collectors;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.calcite.util.ImmutableIntList;
import org.apache.calcite.util.Pair;
@@ -60,14 +63,17 @@ interface IgniteSortAggregateBase extends TraitsAwareIgniteRel {
) {
RelCollation inputCollation = TraitUtils.collation(inputTraits.get(0));
- IntList newCollation = maxPrefix(inputCollation.getKeys(), getGroupSet().asSet());
+ IntList newCollationColls = maxPrefix(inputCollation.getKeys(), getGroupSet().asSet());
- if (newCollation.size() < getGroupSet().cardinality()) {
- return List.of();
+ if (newCollationColls.size() < getGroupSet().cardinality()) {
+ return ImmutableList.of();
}
- return List.of(Pair.of(
- nodeTraits.replace(RelCollations.of(ImmutableIntList.copyOf(newCollation))),
+ List<RelFieldCollation> suitableCollations = inputCollation.getFieldCollations()
+ .stream().filter(k -> newCollationColls.contains(k.getFieldIndex())).collect(Collectors.toList());
+
+ return ImmutableList.of(Pair.of(
+ nodeTraits.replace(RelCollations.of(suitableCollations)),
inputTraits
));
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
index 4606ca6..aaaabbd 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rel/logical/IgniteLogicalTableScan.java
@@ -51,7 +51,7 @@ public class IgniteLogicalTableScan extends ProjectableFilterableTableScan {
* @param tbl Table definition.
* @param proj Projects.
* @param cond Filters.
- * @param requiredColunms Participating colunms.
+ * @param requiredColumns Participating columns.
*/
private IgniteLogicalTableScan(
RelOptCluster cluster,
@@ -59,8 +59,8 @@ public class IgniteLogicalTableScan extends ProjectableFilterableTableScan {
RelOptTable tbl,
@Nullable List<RexNode> proj,
@Nullable RexNode cond,
- @Nullable ImmutableBitSet requiredColunms
+ @Nullable ImmutableBitSet requiredColumns
) {
- super(cluster, traits, List.of(), tbl, proj, cond, requiredColunms);
+ super(cluster, traits, List.of(), tbl, proj, cond, requiredColumns);
}
}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/SortAggregatePlannerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/SortAggregatePlannerTest.java
index d109275..db065e9 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/SortAggregatePlannerTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/SortAggregatePlannerTest.java
@@ -26,8 +26,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.util.ImmutableIntList;
+import org.apache.ignite.internal.sql.engine.rel.IgniteCorrelatedNestedLoopJoin;
+import org.apache.ignite.internal.sql.engine.rel.IgniteLimit;
import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
import org.apache.ignite.internal.sql.engine.rel.IgniteSort;
import org.apache.ignite.internal.sql.engine.rel.agg.IgniteReduceSortAggregate;
@@ -70,6 +73,32 @@ public class SortAggregatePlannerTest extends AbstractAggregatePlannerTest {
assertThat(ex.getMessage(), startsWith("There are not enough rules to produce a node with desired properties"));
}
+ /** Checks if already sorted input exist and involved [Map|Reduce]SortAggregate. */
+ @Test
+ public void testNoSortAppendingWithCorrectCollation() throws Exception {
+ RelFieldCollation coll = new RelFieldCollation(1, RelFieldCollation.Direction.DESCENDING);
+
+ TestTable tbl = createAffinityTable().addIndex(RelCollations.of(coll), "val0Idx");
+
+ IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
+
+ publicSchema.addTable("TEST", tbl);
+
+ String sql = "SELECT ID FROM test WHERE VAL0 IN (SELECT VAL0 FROM test)";
+
+ IgniteRel phys = physicalPlan(
+ sql,
+ publicSchema,
+ "HashSingleAggregateConverterRule", "HashMapReduceAggregateConverterRule",
+ "LogicalTableScanConverterRule"
+ );
+
+ assertNull(
+ findFirstNode(phys, byClass(IgniteSort.class)),
+ "Invalid plan\n" + RelOptUtil.toString(phys)
+ );
+ }
+
/**
* CollationPermuteSingle.
* TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
@@ -165,4 +194,16 @@ public class SortAggregatePlannerTest extends AbstractAggregatePlannerTest {
"Invalid plan\n" + RelOptUtil.toString(phys)
);
}
+
+ @Test
+ public void testEmptyCollationPasshThroughLimit() throws Exception {
+ IgniteSchema publicSchema = createSchema(
+ createTable("TEST", IgniteDistributions.single(), "A", Integer.class));
+
+ assertPlan("SELECT (SELECT test.a FROM test t ORDER BY 1 LIMIT 1) FROM test", publicSchema,
+ hasChildThat(isInstanceOf(IgniteCorrelatedNestedLoopJoin.class)
+ .and(input(1, hasChildThat(isInstanceOf(IgniteLimit.class)
+ .and(input(isInstanceOf(IgniteSort.class)))))))
+ );
+ }
}