Ruben Q L created CALCITE-7641:
----------------------------------

             Summary: Materialize view rules with UnionRewritingPullProgram on 
a HepPlanner throws IllegalArgumentException
                 Key: CALCITE-7641
                 URL: https://issues.apache.org/jira/browse/CALCITE-7641
             Project: Calcite
          Issue Type: Bug
          Components: core
    Affects Versions: 1.42.0
            Reporter: Ruben Q L


It seems all the tests on MaterializedView rules:
 - Run with the default UnionRewritingPullProgram (null, i.e. none) for all the 
rules.
 - Run using Volcano planner.

However, if we try these rules with a certain UnionRewritingPullProgram, and 
apply them using a HepPlanner, for example forcing the situation with this test 
to be added to MaterializedViewRelOptRulesTest:
{code:java}
  @Test void testJoinAggregateMaterializationNoAggregateFuncs9Hep() {
    final MaterializedViewTester hepTester =
        new MaterializedViewTester() {
          @Override protected List<RelNode> optimize(RelNode queryRel,
              List<RelOptMaterialization> materializationList) {
            final HepProgram unionRewritingPullProgram = new HepProgramBuilder()
                .addRuleInstance(ProjectRemoveRule.Config.DEFAULT.toRule())
                .build();
            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);
                  final RelNode rootRel = planner.findBestExp();
                  return requireNonNull(rootRel, "could not implement exp");
                };
            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();
  }
{code}
It fails with:
{noformat}
java.lang.IllegalArgumentException
        at 
com.google.common.base.Preconditions.checkArgument(Preconditions.java:127)
        at org.apache.calcite.plan.hep.HepRelVertex.<init>(HepRelVertex.java:54)
        at 
org.apache.calcite.plan.hep.HepPlanner.addRelToGraph(HepPlanner.java:981)
        at org.apache.calcite.plan.hep.HepPlanner.setRoot(HepPlanner.java:242)
        at 
org.apache.calcite.rel.rules.materialize.MaterializedViewAggregateRule.rewriteQuery(MaterializedViewAggregateRule.java:279)
        at 
org.apache.calcite.rel.rules.materialize.MaterializedViewRule.perform(MaterializedViewRule.java:390)
        at 
org.apache.calcite.rel.rules.materialize.MaterializedViewOnlyAggregateRule.onMatch(MaterializedViewOnlyAggregateRule.java:71)
        at 
org.apache.calcite.plan.AbstractRelOptPlanner.fireRule(AbstractRelOptPlanner.java:380)
{noformat}

The reason is that UnionRewritingPullProgram (used inside {{rewriteQuery}}) 
will try to apply this HepProgram (using of course a HepPlanner):
{code:java}
    ...
    if (unionRewritingPullProgram != null) {
      final HepPlanner tmpPlanner = new HepPlanner(unionRewritingPullProgram);
      tmpPlanner.setRoot(newNode);
      newNode = tmpPlanner.findBestExp();
      target = newNode.getInput(0);
    }
{code}

The reason is that, since the MaterializedViewRule is applied using a 
HepPlanner, the RelNode that fires the rule contains HepRelVertex as "wrappers" 
on its inputs (the whole subtree nodes are wrapped in HepRelVertex instances). 
If UnionRewritingPullProgram is non-null, a new HepPlanner is created, and we 
tried to apply said program on that subtree. However, when setting the root on 
that second HepPlanner, and initializing the graph, when trying to create the 
"new" HepRelVertex, there's a precondition violation, because the RelNode that 
we are trying to add is also a HepRelVertex (from the subtree that fired the 
MaterializedViewRule):

{code:java}
  HepRelVertex(RelNode rel) {
    super(rel.getCluster(), rel.getTraitSet());
    currentRel = requireNonNull(rel, "rel");
    checkArgument(!(rel instanceof HepRelVertex)); // fails here
  }
{code}

Basically, we cannot apply a HepProgram on a tree containing already HepVertex, 
and this is violated on this scenario.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to