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)