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

hyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 24dd266  [CALCITE-3928] Trim unused fields before materialized view 
matching (dz)
24dd266 is described below

commit 24dd26640db01114c6931d6615b90a63969ffc42
Author: xzh <953396...@qq.com>
AuthorDate: Tue Apr 21 18:54:31 2020 +0800

    [CALCITE-3928] Trim unused fields before materialized view matching (dz)
    
    Close #1936
---
 .../calcite/plan/RelOptMaterializations.java       |  22 +++++
 .../materialize/NormalizationTrimFieldTest.java    | 103 +++++++++++++++++++++
 2 files changed, 125 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java 
b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
index e6f1dbd..d06ec2b 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
@@ -21,6 +21,7 @@ import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.plan.hep.HepProgram;
 import org.apache.calcite.plan.hep.HepProgramBuilder;
 import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.rules.CalcMergeRule;
 import org.apache.calcite.rel.rules.FilterAggregateTransposeRule;
 import org.apache.calcite.rel.rules.FilterCalcMergeRule;
@@ -34,6 +35,8 @@ import org.apache.calcite.rel.rules.ProjectMergeRule;
 import org.apache.calcite.rel.rules.ProjectRemoveRule;
 import org.apache.calcite.rel.rules.ProjectSetOpTransposeRule;
 import org.apache.calcite.rel.rules.ProjectToCalcRule;
+import org.apache.calcite.sql2rel.RelFieldTrimmer;
+import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.Pair;
 import org.apache.calcite.util.graph.DefaultDirectedGraph;
 import org.apache.calcite.util.graph.DefaultEdge;
@@ -192,6 +195,9 @@ public abstract class RelOptMaterializations {
 
     // Push filters to the bottom, and combine projects on top.
     RelNode target = materialization.queryRel;
+    // try to trim unused field in relational expressions.
+    root = trimUnusedfields(root);
+    target = trimUnusedfields(target);
     HepProgram program =
         new HepProgramBuilder()
             .addRuleInstance(FilterProjectTransposeRule.INSTANCE)
@@ -224,6 +230,22 @@ public abstract class RelOptMaterializations {
   }
 
   /**
+   * Trim unused fields in relational expressions.
+   */
+  private static RelNode trimUnusedfields(RelNode relNode) {
+    final List<RelOptTable> relOptTables = RelOptUtil.findAllTables(relNode);
+    RelOptSchema relOptSchema = null;
+    if (relOptTables.size() != 0) {
+      relOptSchema = relOptTables.get(0).getRelOptSchema();
+    }
+    final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(
+        relNode.getCluster(), relOptSchema);
+    final RelFieldTrimmer relFieldTrimmer = new RelFieldTrimmer(null, 
relBuilder);
+    final RelNode rel = relFieldTrimmer.trim(relNode);
+    return rel;
+  }
+
+  /**
    * Returns whether {@code table} uses one or more of the tables in
    * {@code usedTables}.
    */
diff --git 
a/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java
 
b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java
new file mode 100644
index 0000000..567d952
--- /dev/null
+++ 
b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.calcite.materialize;
+
+import org.apache.calcite.plan.RelOptMaterialization;
+import org.apache.calcite.plan.RelOptMaterializations;
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.plan.RelTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.AbstractTable;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.SqlToRelTestBase;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.tools.RelBuilder;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.Pair;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.apache.calcite.test.Matchers.isLinux;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class NormalizationTrimFieldTest extends SqlToRelTestBase {
+
+  public static Frameworks.ConfigBuilder config() {
+    final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
+    rootSchema.add("mv0", new AbstractTable() {
+      @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+        return typeFactory.builder()
+            .add("deptno", SqlTypeName.INTEGER)
+            .add("count_sal", SqlTypeName.BIGINT)
+            .build();
+      }
+    });
+    return Frameworks.newConfigBuilder()
+        .parserConfig(SqlParser.Config.DEFAULT)
+        .defaultSchema(
+            CalciteAssert.addSchema(rootSchema, 
CalciteAssert.SchemaSpec.SCOTT_WITH_TEMPORAL))
+        .traitDefs((List<RelTraitDef>) null);
+  }
+
+  @Test public void testMVTrimUnusedFiled() {
+    final RelBuilder relBuilder = RelBuilder.create(config().build());
+    final LogicalProject project = (LogicalProject) relBuilder.scan("EMP")
+        .project(relBuilder.field("EMPNO"),
+            relBuilder.field("ENAME"),
+            relBuilder.field("JOB"),
+            relBuilder.field("SAL"),
+            relBuilder.field("DEPTNO")).build();
+    final LogicalAggregate aggregate = (LogicalAggregate) 
relBuilder.push(project)
+        .aggregate(
+            relBuilder.groupKey(relBuilder.field(1, 0, "DEPTNO")
+        ), relBuilder.count(relBuilder.field(1, 0, "SAL"))).build();
+    final ImmutableBitSet groupSet = ImmutableBitSet.of(4);
+    final AggregateCall count = aggregate.getAggCallList().get(0);
+    final AggregateCall call = AggregateCall.create(count.getAggregation(), 
count.isDistinct(),
+        count.isApproximate(), count.ignoreNulls(), ImmutableList.of(3),
+        count.filterArg, count.collation, count.getType(), count.getName());
+    final RelNode query = LogicalAggregate.create(project, 
aggregate.getHints(),
+        groupSet, ImmutableList.of(groupSet), ImmutableList.of(call));
+    final RelNode target = aggregate;
+    final RelNode replacement = relBuilder.scan("mv0").build();
+    final RelOptMaterialization relOptMaterialization = new 
RelOptMaterialization(replacement,
+        target, null, Lists.newArrayList("mv0"));
+    final List<Pair<RelNode, List<RelOptMaterialization>>> relOptimized = 
RelOptMaterializations
+        .useMaterializedViews(query, ImmutableList.of(relOptMaterialization));
+
+    final String optimized = ""
+        + "LogicalProject(deptno=[CAST($0):TINYINT], count_sal=[$1])\n"
+        + "  LogicalTableScan(table=[[mv0]])\n";
+    final String relOptimizedStr = 
RelOptUtil.toString(relOptimized.get(0).getKey());
+    assertThat(isLinux(optimized).matches(relOptimizedStr), is(true));
+  }
+}

Reply via email to