From ebba3ec5253f6bee78ca471481b3f7b454c3ba89 Mon Sep 17 00:00:00 2001 From: Ruben Quesada Lopez Date: Tue, 7 Jul 2026 11:47:03 +0100 Subject: [PATCH] [CALCITE-7641] Materialize view rules with UnionRewritingPullProgram on a HepPlanner throws IllegalArgumentException --- .../MaterializedViewAggregateRule.java | 5 + .../materialize/MaterializedViewJoinRule.java | 9 +- .../test/MaterializedViewRelOptRulesTest.java | 112 ++++++++++++++++++ 3 files changed, 124 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java index 404d0200bab1..538723661d60 100644 --- a/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java +++ b/core/src/main/java/org/apache/calcite/rel/rules/materialize/MaterializedViewAggregateRule.java @@ -23,6 +23,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.plan.hep.HepRelVertex; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.Aggregate; import org.apache.calcite.rel.core.AggregateCall; @@ -259,6 +260,10 @@ public abstract class MaterializedViewAggregateRule[CALCITE-7641] + * Materialize view rules with UnionRewritingPullProgram on a HepPlanner + * throws IllegalArgumentException. */ + @Test void testJoinAggregateMaterializationNoAggregateFuncs9Hep() { + // Tester using a HepPlanner instead of Volcano + final MaterializedViewTester hepTester = + new MaterializedViewTester() { + @Override protected List optimize(RelNode queryRel, + List materializationList) { + // Dummy UnionRewritingPullProgram + final HepProgram unionRewritingPullProgram = new HepProgramBuilder().build(); + // MaterializedViewRule with UnionRewritingPullProgram + final HepProgram mainProgram = new HepProgramBuilder() + .addRuleInstance(MaterializedViewOnlyAggregateRule.Config.DEFAULT + .withUnionRewritingPullProgram(unionRewritingPullProgram).toRule()) + .build(); + final HepPlanner hepPlanner = new HepPlanner(mainProgram); + final Program program = + (planner, rel, requiredOutputTraits, materializations, lattices) -> { + for (RelOptMaterialization materialization : materializations) { + planner.addMaterialization(materialization); + } + planner.setRoot(rel); + return planner.findBestExp(); + }; + return ImmutableList.of( + program.run(hepPlanner, queryRel, queryRel.getCluster().traitSet(), + materializationList, ImmutableList.of())); + } + }; + + String materialize = "select \"depts\".\"deptno\", \"dependents\".\"empid\"\n" + + "from \"depts\"\n" + + "join \"dependents\" on (\"depts\".\"name\" = \"dependents\".\"name\")\n" + + "join \"locations\" on (\"locations\".\"name\" = \"dependents\".\"name\")\n" + + "join \"emps\" on (\"emps\".\"deptno\" = \"depts\".\"deptno\")\n" + + "where \"depts\".\"deptno\" > 11 and \"depts\".\"deptno\" < 19\n" + + "group by \"depts\".\"deptno\", \"dependents\".\"empid\""; + String query = "select \"dependents\".\"empid\"\n" + + "from \"depts\"\n" + + "join \"dependents\" on (\"depts\".\"name\" = \"dependents\".\"name\")\n" + + "join \"locations\" on (\"locations\".\"name\" = \"dependents\".\"name\")\n" + + "join \"emps\" on (\"emps\".\"deptno\" = \"depts\".\"deptno\")\n" + + "where \"depts\".\"deptno\" > 10 and \"depts\".\"deptno\" < 20\n" + + "group by \"dependents\".\"empid\""; + + MaterializedViewFixture.create(query, hepTester) + .withMaterializations(ImmutableList.of(Pair.of(materialize, "MV0"))) + .checkingThatResultContains("EnumerableTableScan(table=[[hr, MV0]])") + .ok(); + } + @Test void testJoinAggregateMaterializationNoAggregateFuncs10() { sql("select \"depts\".\"name\", \"dependents\".\"name\" as \"name2\", " + "\"emps\".\"deptno\", \"depts\".\"deptno\" as \"deptno2\", " @@ -950,6 +1010,58 @@ protected final MaterializedViewFixture sql(String materialize, .ok(); } + /** Test case for + * [CALCITE-7641] + * Materialize view rules with UnionRewritingPullProgram on a HepPlanner + * throws IllegalArgumentException. */ + @Test void testJoinMaterialization10Hep() { + // Tester using a HepPlanner instead of Volcano + final MaterializedViewTester hepTester = + new MaterializedViewTester() { + @Override protected List optimize(RelNode queryRel, + List materializationList) { + // Dummy UnionRewritingPullProgram + final HepProgram unionRewritingPullProgram = new HepProgramBuilder().build(); + final HepProgram mainProgram = new HepProgramBuilder() + .addRuleInstance(MaterializedViewRules.JOIN) + .addRuleInstance(MaterializedViewRules.PROJECT_JOIN) + .addRuleInstance(MaterializedViewRules.PROJECT_FILTER) + // MaterializedViewOnlyFilterRule with UnionRewritingPullProgram + .addRuleInstance(MaterializedViewOnlyFilterRule.Config.DEFAULT + .withUnionRewritingPullProgram(unionRewritingPullProgram).toRule()) + .build(); + final HepPlanner hepPlanner = new HepPlanner(mainProgram); + final Program program = + (planner, rel, requiredOutputTraits, materializations, lattices) -> { + for (RelOptMaterialization materialization : materializations) { + planner.addMaterialization(materialization); + } + planner.setRoot(rel); + return planner.findBestExp(); + }; + return ImmutableList.of( + program.run(hepPlanner, queryRel, queryRel.getCluster().traitSet(), + materializationList, ImmutableList.of())); + } + }; + + String materialize = "select \"depts\".\"deptno\", \"dependents\".\"empid\"\n" + + "from \"depts\"\n" + + "join \"dependents\" on (\"depts\".\"name\" = \"dependents\".\"name\")\n" + + "join \"emps\" on (\"emps\".\"deptno\" = \"depts\".\"deptno\")\n" + + "where \"depts\".\"deptno\" > 30"; + String query = "select \"dependents\".\"empid\"\n" + + "from \"depts\"\n" + + "join \"dependents\" on (\"depts\".\"name\" = \"dependents\".\"name\")\n" + + "join \"emps\" on (\"emps\".\"deptno\" = \"depts\".\"deptno\")\n" + + "where \"depts\".\"deptno\" > 10"; + + MaterializedViewFixture.create(query, hepTester) + .withMaterializations(ImmutableList.of(Pair.of(materialize, "MV0"))) + .checkingThatResultContains("EnumerableTableScan(table=[[hr, MV0]])") + .ok(); + } + @Test void testJoinMaterialization11() { sql("select \"empid\" from \"emps\"\n" + "join \"depts\" using (\"deptno\")",