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 2020/05/15 15:37:34 UTC
[ignite] branch ignite-12248 updated: IGNITE-12912 Calcite
integration: Add filters merge rule to the planner (#7806)
This is an automated email from the ASF dual-hosted git repository.
tledkov pushed a commit to branch ignite-12248
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/ignite-12248 by this push:
new da7f92c IGNITE-12912 Calcite integration: Add filters merge rule to the planner (#7806)
da7f92c is described below
commit da7f92cb98a6d8e1990aa856f38607629a33f327
Author: tledkov <tl...@gridgain.com>
AuthorDate: Fri May 15 18:36:43 2020 +0300
IGNITE-12912 Calcite integration: Add filters merge rule to the planner (#7806)
---
.../query/calcite/prepare/PlannerPhase.java | 4 +
.../rule/logical/LogicalFilterMergeRule.java | 46 +++++++++
.../logical/LogicalFilterProjectTransposeRule.java | 38 ++++++++
.../processors/query/calcite/PlannerTest.java | 105 +++++++++++++++++++++
4 files changed, 193 insertions(+)
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
index 50be506..8c47744 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
@@ -34,6 +34,8 @@ import org.apache.ignite.internal.processors.query.calcite.rule.TableModifyConve
import org.apache.ignite.internal.processors.query.calcite.rule.UnionConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.UnionTraitsTraitsPropagationRule;
import org.apache.ignite.internal.processors.query.calcite.rule.ValuesConverterRule;
+import org.apache.ignite.internal.processors.query.calcite.rule.logical.LogicalFilterMergeRule;
+import org.apache.ignite.internal.processors.query.calcite.rule.logical.LogicalFilterProjectTransposeRule;
import static org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePrograms.cbo;
import static org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePrograms.decorrelate;
@@ -73,6 +75,8 @@ public enum PlannerPhase {
ProjectConverterRule.INSTANCE,
ProjectTraitsPropagationRule.INSTANCE,
FilterConverterRule.INSTANCE,
+ LogicalFilterMergeRule.INSTANCE,
+ LogicalFilterProjectTransposeRule.INSTANCE,
FilterTraitsPropagationRule.INSTANCE,
TableModifyConverterRule.INSTANCE,
UnionMergeRule.INSTANCE,
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterMergeRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterMergeRule.java
new file mode 100644
index 0000000..c7eaf6a
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterMergeRule.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.rule.logical;
+
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.rules.FilterMergeRule;
+
+/**
+ *
+ */
+public class LogicalFilterMergeRule extends RelOptRule {
+ public static final RelOptRule INSTANCE = new LogicalFilterMergeRule();
+
+ /**
+ *
+ */
+ public LogicalFilterMergeRule() {
+ super(
+ operand(LogicalFilter.class,
+ operand(LogicalFilter.class, any())),
+ RelFactories.LOGICAL_BUILDER, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onMatch(RelOptRuleCall call) {
+ FilterMergeRule.INSTANCE.onMatch(call);
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterProjectTransposeRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterProjectTransposeRule.java
new file mode 100644
index 0000000..3410df3
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/logical/LogicalFilterProjectTransposeRule.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.rule.logical;
+
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
+
+/**
+ *
+ */
+public class LogicalFilterProjectTransposeRule extends FilterProjectTransposeRule {
+ /** */
+ public static final RelOptRule INSTANCE = new LogicalFilterProjectTransposeRule();
+
+ /** */
+ public LogicalFilterProjectTransposeRule() {
+ super(LogicalFilter.class, LogicalProject.class, true, true,
+ RelFactories.LOGICAL_BUILDER);
+ }
+}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
index 382a5db..7893a1f 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/PlannerTest.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import org.apache.calcite.DataContext;
import org.apache.calcite.linq4j.Enumerable;
@@ -29,12 +30,14 @@ import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.ConventionTraitDef;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.plan.RelTraitDef;
import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.RelRoot;
+import org.apache.calcite.rel.RelVisitor;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeImpl;
@@ -72,6 +75,7 @@ import org.apache.ignite.internal.processors.query.calcite.prepare.PlannerPhase;
import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.schema.DistributedTable;
@@ -2323,6 +2327,107 @@ public class PlannerTest extends GridCommonAbstractTest {
assertNotNull(nodes);
}
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testMergeFilters() throws Exception {
+ IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
+
+ TestTable testTbl = new TestTable(
+ new RelDataTypeFactory.Builder(f)
+ .add("ID", f.createJavaType(Integer.class))
+ .add("VAL", f.createJavaType(String.class))
+ .build()) {
+ };
+
+ IgniteSchema publicSchema = new IgniteSchema("PUBLIC");
+
+ publicSchema.addTable("TEST", testTbl);
+
+ SchemaPlus schema = createRootSchema(false)
+ .add("PUBLIC", publicSchema);
+
+ String sql = "" +
+ "SELECT val from (\n" +
+ " SELECT * \n" +
+ " FROM TEST \n" +
+ " WHERE VAL = 10) \n" +
+ "WHERE VAL = 10";
+
+ RelTraitDef<?>[] traitDefs = {
+ ConventionTraitDef.INSTANCE
+ };
+
+ PlanningContext ctx = PlanningContext.builder()
+ .localNodeId(F.first(nodes))
+ .originatingNodeId(F.first(nodes))
+ .parentContext(Contexts.empty())
+ .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG)
+ .defaultSchema(schema)
+ .traitDefs(traitDefs)
+ .build())
+ .logger(log)
+ .query(sql)
+ .parameters(new Object[]{2})
+ .topologyVersion(AffinityTopologyVersion.NONE)
+ .build();
+
+ RelRoot relRoot;
+
+ try (IgnitePlanner planner = ctx.planner()){
+ assertNotNull(planner);
+
+ String query = ctx.query();
+
+ assertNotNull(query);
+
+ // Parse
+ SqlNode sqlNode = planner.parse(query);
+
+ // Validate
+ sqlNode = planner.validate(sqlNode);
+
+ // Convert to Relational operators graph
+ relRoot = planner.rel(sqlNode);
+
+ RelNode rel = relRoot.rel;
+
+ // Transformation chain
+ rel = planner.transform(PlannerPhase.HEURISTIC_OPTIMIZATION, rel.getTraitSet(), rel);
+
+ RelTraitSet desired = rel.getCluster()
+ .traitSetOf(IgniteConvention.INSTANCE)
+ .replace(IgniteDistributions.single());
+
+ RelNode phys = planner.transform(PlannerPhase.OPTIMIZATION, desired, rel);
+
+ assertNotNull(phys);
+
+ AtomicInteger filterCnt = new AtomicInteger();
+
+ // Counts filters af the plan.
+ phys.childrenAccept(
+ new RelVisitor() {
+ @Override public void visit(RelNode node, int ordinal, RelNode parent) {
+ if (node instanceof IgniteFilter)
+ filterCnt.incrementAndGet();
+
+ super.visit(node, ordinal, parent);
+ }
+ }
+ );
+
+ // Checks that two filter merged into one filter.
+ // Expected plan:
+ // IgniteProject(VAL=[$1])
+ // IgniteProject(ID=[$0], VAL=[$1])
+ // IgniteFilter(condition=[=(CAST($1):INTEGER, 10)])
+ // IgniteTableScan(table=[[PUBLIC, TEST]])
+ assertEquals(1, filterCnt.get());
+ }
+ }
+
/** */
private NodesMapping intermediateMapping(@NotNull AffinityTopologyVersion topVer, int desiredCount, @Nullable Predicate<ClusterNode> filter) {
List<UUID> nodes = desiredCount == 1 ? select(this.nodes, 0) : select(this.nodes, 0, 1, 2, 3);