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();
+    }
 }