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 2022/02/15 10:10:39 UTC
[ignite] branch sql-calcite updated: IGNITE-14916 Calcite. RuntimeHashIndex scan must filter result by predicate (#9819)
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 46367e1 IGNITE-14916 Calcite. RuntimeHashIndex scan must filter result by predicate (#9819)
46367e1 is described below
commit 46367e1a0a25e853a73f4490b568bfea847e8785
Author: Taras Ledkov <tl...@gridgain.com>
AuthorDate: Tue Feb 15 13:10:13 2022 +0300
IGNITE-14916 Calcite. RuntimeHashIndex scan must filter result by predicate (#9819)
---
.../query/calcite/exec/LogicalRelImplementor.java | 3 +++
.../query/calcite/exec/RuntimeHashIndex.java | 23 ++++++++++++++++++----
.../query/calcite/exec/rel/IndexSpoolNode.java | 4 +++-
.../query/calcite/rel/IgniteHashIndexSpool.java | 8 +++++---
.../rule/FilterSpoolMergeToHashIndexSpoolRule.java | 19 +-----------------
.../exec/rel/HashIndexSpoolExecutionTest.java | 7 +++++++
.../integration/HashSpoolIntegrationTest.java | 16 +++++++++++++++
7 files changed, 54 insertions(+), 26 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 12d02f7..b6a99bf 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
@@ -517,10 +517,13 @@ public class LogicalRelImplementor<Row> implements IgniteRelVisitor<Node<Row>> {
@Override public Node<Row> visit(IgniteHashIndexSpool rel) {
Supplier<Row> searchRow = expressionFactory.rowSource(rel.searchRow());
+ Predicate<Row> filter = expressionFactory.predicate(rel.condition(), rel.getRowType());
+
IndexSpoolNode<Row> node = IndexSpoolNode.createHashSpool(
ctx,
rel.getRowType(),
ImmutableBitSet.of(rel.keys()),
+ filter,
searchRow
);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeHashIndex.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeHashIndex.java
index 303103f..8329486 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeHashIndex.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/RuntimeHashIndex.java
@@ -21,13 +21,16 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Predicate;
import java.util.function.Supplier;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.internal.processors.query.calcite.exec.exp.agg.GroupKey;
+import org.apache.ignite.internal.util.lang.GridFilteredIterator;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Runtime hash index based on on-heap hash map.
@@ -81,8 +84,8 @@ public class RuntimeHashIndex<Row> implements RuntimeIndex<Row> {
}
/** */
- public Iterable<Row> scan(Supplier<Row> searchRow) {
- return new IndexScan(searchRow);
+ public Iterable<Row> scan(Supplier<Row> searchRow, @Nullable Predicate<Row> filter) {
+ return new IndexScan(searchRow, filter);
}
/** */
@@ -108,11 +111,16 @@ public class RuntimeHashIndex<Row> implements RuntimeIndex<Row> {
/** Search row. */
private final Supplier<Row> searchRow;
+ /** Row filter. */
+ private final Predicate<Row> filter;
+
/**
* @param searchRow Search row.
+ * @param filter Scan condition.
*/
- IndexScan(Supplier<Row> searchRow) {
+ IndexScan(Supplier<Row> searchRow, @Nullable Predicate<Row> filter) {
this.searchRow = searchRow;
+ this.filter = filter;
}
/** {@inheritDoc} */
@@ -129,7 +137,14 @@ public class RuntimeHashIndex<Row> implements RuntimeIndex<Row> {
List<Row> eqRows = rows.get(key);
- return eqRows == null ? Collections.emptyIterator() : eqRows.iterator();
+ if (eqRows == null)
+ return Collections.emptyIterator();
+
+ return filter == null ? eqRows.iterator() : new GridFilteredIterator<Row>(eqRows.iterator()) {
+ @Override protected boolean accept(Row row) {
+ return filter.test(row);
+ }
+ };
}
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/IndexSpoolNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/IndexSpoolNode.java
index e6b44dd..93e8b71 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/IndexSpoolNode.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/IndexSpoolNode.java
@@ -29,6 +29,7 @@ import org.apache.ignite.internal.processors.query.calcite.exec.RuntimeHashIndex
import org.apache.ignite.internal.processors.query.calcite.exec.RuntimeIndex;
import org.apache.ignite.internal.processors.query.calcite.exec.RuntimeSortedIndex;
import org.apache.ignite.internal.util.typedef.F;
+import org.jetbrains.annotations.Nullable;
/**
* Index spool node.
@@ -189,6 +190,7 @@ public class IndexSpoolNode<Row> extends AbstractNode<Row> implements SingleNode
ExecutionContext<Row> ctx,
RelDataType rowType,
ImmutableBitSet keys,
+ @Nullable Predicate<Row> filter,
Supplier<Row> searchRow
) {
RuntimeHashIndex<Row> idx = new RuntimeHashIndex<>(ctx, keys);
@@ -196,7 +198,7 @@ public class IndexSpoolNode<Row> extends AbstractNode<Row> implements SingleNode
ScanNode<Row> scan = new ScanNode<>(
ctx,
rowType,
- idx.scan(searchRow)
+ idx.scan(searchRow, filter)
);
return new IndexSpoolNode<>(ctx, rowType, idx, scan);
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteHashIndexSpool.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteHashIndexSpool.java
index 055d192..738b81f 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteHashIndexSpool.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteHashIndexSpool.java
@@ -46,7 +46,7 @@ public class IgniteHashIndexSpool extends Spool implements IgniteRel {
/** Keys (number of the columns at the input row) to build hash index. */
private final ImmutableBitSet keys;
- /** Condition (used to calculate selectivity). */
+ /** Filters. */
private final RexNode cond;
/** */
@@ -77,7 +77,7 @@ public class IgniteHashIndexSpool extends Spool implements IgniteRel {
input.getTraitSet().replace(IgniteConvention.INSTANCE),
input.getInputs().get(0),
input.getExpressionList("searchRow"),
- null
+ input.getExpression("condition")
);
}
@@ -105,7 +105,9 @@ public class IgniteHashIndexSpool extends Spool implements IgniteRel {
@Override public RelWriter explainTerms(RelWriter pw) {
RelWriter writer = super.explainTerms(pw);
- return writer.item("searchRow", searchRow);
+ return writer
+ .item("searchRow", searchRow)
+ .item("condition", cond);
}
/** {@inheritDoc} */
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/FilterSpoolMergeToHashIndexSpoolRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/FilterSpoolMergeToHashIndexSpoolRule.java
index 82f6008..dae8f27 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/FilterSpoolMergeToHashIndexSpoolRule.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/FilterSpoolMergeToHashIndexSpoolRule.java
@@ -20,16 +20,13 @@ import java.util.List;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.RelRule;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Filter;
import org.apache.calcite.rel.core.Spool;
-import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexUtil;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteHashIndexSpool;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableSpool;
@@ -39,8 +36,6 @@ import org.apache.ignite.internal.processors.query.calcite.util.RexUtils;
import org.apache.ignite.internal.util.typedef.F;
import org.immutables.value.Value;
-import static org.apache.ignite.internal.processors.query.calcite.util.RexUtils.isBinaryComparison;
-
/**
* Rule that pushes filter into the spool.
*/
@@ -60,7 +55,6 @@ public class FilterSpoolMergeToHashIndexSpoolRule extends RelRule<FilterSpoolMer
final IgniteTableSpool spool = call.rel(1);
RelOptCluster cluster = spool.getCluster();
- RexBuilder builder = RexUtils.builder(cluster);
RelTraitSet trait = spool.getTraitSet();
CorrelationTrait filterCorr = TraitUtils.correlation(filter);
@@ -70,20 +64,9 @@ public class FilterSpoolMergeToHashIndexSpoolRule extends RelRule<FilterSpoolMer
RelNode input = spool.getInput();
- RexNode condition0 = RexUtil.expandSearch(builder, null, filter.getCondition());
-
- condition0 = RexUtil.toCnf(builder, condition0);
-
- List<RexNode> conjunctions = RelOptUtil.conjunctions(condition0);
-
- //TODO: https://issues.apache.org/jira/browse/IGNITE-14916
- for (RexNode rexNode : conjunctions)
- if (!isBinaryComparison(rexNode))
- return;
-
List<RexNode> searchRow = RexUtils.buildHashSearchRow(
cluster,
- condition0,
+ filter.getCondition(),
spool.getRowType(),
null,
false
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashIndexSpoolExecutionTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashIndexSpoolExecutionTest.java
index 9b84f4f..e18646b 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashIndexSpoolExecutionTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashIndexSpoolExecutionTest.java
@@ -85,6 +85,11 @@ public class HashIndexSpoolExecutionTest extends AbstractExecutionTest {
null,
new Object[] {size / 2 + 1, null, null},
eqCnt
+ ),
+ new GridTuple3(
+ (Predicate<Object[]>)r -> ((int)r[2]) == 0,
+ new Object[] {size / 2 + 1, null, null},
+ 1
)
};
}
@@ -115,6 +120,7 @@ public class HashIndexSpoolExecutionTest extends AbstractExecutionTest {
ctx,
rowType,
ImmutableBitSet.of(0),
+ testFilter,
() -> searchRow
);
@@ -157,6 +163,7 @@ public class HashIndexSpoolExecutionTest extends AbstractExecutionTest {
ctx,
rowType,
ImmutableBitSet.of(0, 1),
+ null,
() -> searchRow
);
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/HashSpoolIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/HashSpoolIntegrationTest.java
index cca21ef..3eeb9c3 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/HashSpoolIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/HashSpoolIntegrationTest.java
@@ -64,4 +64,20 @@ public class HashSpoolIntegrationTest extends AbstractBasicIntegrationTest {
.returns(1, 1, 1, 1)
.check();
}
+
+ /** */
+ @Test
+ public void testHashSpoolCondition() {
+ executeSql("CREATE TABLE t(i INTEGER)");
+ executeSql("INSERT INTO t VALUES (0), (1), (2)");
+
+ String sql = "SELECT i, (SELECT i FROM t WHERE i=t1.i AND i-1=0) FROM t AS t1";
+
+ assertQuery(sql)
+ .matches(QueryChecker.containsSubPlan("IgniteHashIndexSpool"))
+ .returns(0, null)
+ .returns(1, 1)
+ .returns(2, null)
+ .check();
+ }
}