/* * 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.eigenbase.test; import org.eigenbase.rel.*; import org.eigenbase.rel.rules.*; import org.eigenbase.relopt.hep.*; import org.junit.Test; /** * HepPlannerTest is a unit test for {@link HepPlanner}. See {@link * RelOptRulesTest} for an explanation of how to add tests; the tests in this * class are targeted at exercising the planner, and use specific rules for * convenience only, whereas the tests in that class are targeted at exercising * specific rules, and use the planner for convenience only. Hence the split. */ public class HepPlannerTest extends RelOptTestBase { //~ Static fields/initializers --------------------------------------------- private static final String UNION_TREE = "(select name from dept union select ename from emp)" + " union (select ename from bonus)"; //~ Methods ---------------------------------------------------------------- protected DiffRepository getDiffRepos() { return DiffRepository.lookup(HepPlannerTest.class); } @Test public void testRuleClass() throws Exception { // Verify that an entire class of rules can be applied. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addRuleClass(CoerceInputsRule.class); HepPlanner planner = new HepPlanner( programBuilder.build()); planner.addRule(new CoerceInputsRule(UnionRel.class, false)); planner.addRule(new CoerceInputsRule(IntersectRel.class, false)); checkPlanning( planner, "(select name from dept union select ename from emp)" + " intersect (select fname from customer.contact)"); } @Test public void testRuleDescription() throws Exception { // Verify that a rule can be applied via its description. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addRuleByDescription("FilterToCalcRule"); HepPlanner planner = new HepPlanner( programBuilder.build()); planner.addRule(FilterToCalcRule.INSTANCE); checkPlanning( planner, "select name from sales.dept where deptno=12"); } @Test public void testMatchLimitOneTopDown() throws Exception { // Verify that only the top union gets rewritten. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addMatchOrder(HepMatchOrder.TOP_DOWN); programBuilder.addMatchLimit(1); programBuilder.addRuleInstance(UnionToDistinctRule.INSTANCE); checkPlanning( programBuilder.build(), UNION_TREE); } @Test public void testMatchLimitOneBottomUp() throws Exception { // Verify that only the bottom union gets rewritten. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addMatchLimit(1); programBuilder.addMatchOrder(HepMatchOrder.BOTTOM_UP); programBuilder.addRuleInstance(UnionToDistinctRule.INSTANCE); checkPlanning( programBuilder.build(), UNION_TREE); } @Test public void testMatchUntilFixpoint() throws Exception { // Verify that both unions get rewritten. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addMatchLimit(HepProgram.MATCH_UNTIL_FIXPOINT); programBuilder.addRuleInstance(UnionToDistinctRule.INSTANCE); checkPlanning( programBuilder.build(), UNION_TREE); } @Test public void testReplaceCommonSubexpression() throws Exception { // Note that here it may look like the rule is firing // twice, but actually it's only firing once on the // common subexpression. The purpose of this test // is to make sure the planner can deal with // rewriting something used as a common subexpression // twice by the same parent (the join in this case). checkPlanning( RemoveTrivialProjectRule.INSTANCE, "select d1.deptno from (select * from dept) d1," + " (select * from dept) d2"); } @Test public void testSubprogram() throws Exception { // Verify that subprogram gets re-executed until fixpoint. // In this case, the first time through we limit it to generate // only one calc; the second time through it will generate // a second calc, and then merge them. HepProgramBuilder subprogramBuilder = HepProgram.builder(); subprogramBuilder.addMatchOrder(HepMatchOrder.TOP_DOWN); subprogramBuilder.addMatchLimit(1); subprogramBuilder.addRuleInstance(ProjectToCalcRule.INSTANCE); subprogramBuilder.addRuleInstance(MergeCalcRule.INSTANCE); HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addSubprogram(subprogramBuilder.build()); checkPlanning( programBuilder.build(), "select upper(ename) from (select lower(ename) as ename from emp)"); } @Test public void testGroup() throws Exception { // Verify simultaneous application of a group of rules. // Intentionally add them in the wrong order to make sure // that order doesn't matter within the group. HepProgramBuilder programBuilder = HepProgram.builder(); programBuilder.addGroupBegin(); programBuilder.addRuleInstance(MergeCalcRule.INSTANCE); programBuilder.addRuleInstance(ProjectToCalcRule.INSTANCE); programBuilder.addRuleInstance(FilterToCalcRule.INSTANCE); programBuilder.addGroupEnd(); checkPlanning( programBuilder.build(), "select upper(name) from dept where deptno=20"); } } // End HepPlannerTest.java