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