[
https://issues.apache.org/jira/browse/CALCITE-5254?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17597958#comment-17597958
]
Steven Talbot commented on CALCITE-5254:
----------------------------------------
The loop gets stuck because it is checking if it makes any progress, and the
TrivialRule will repeatedly substitute the Scan in the target into the Scan in
the query, so it thinks that it has made progress. However, the query hasn't
changed since we've just substituted the leaf node for an identity, and the
loop continues, indefinitely.
I think the solution is to simply block the trivial rule from substituting if
the match is MutableScan.
{noformat}
diff --git
a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
index 8044fca68..04ff84214 100644
--- a/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
+++ b/core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
@@ -1059,7 +1059,7 @@ private TrivialRule() {
}
@Override public @Nullable UnifyResult apply(UnifyRuleCall call) {
- if (call.query.equals(call.target)) {
+ if (call.query.equals(call.target) && !(call.query instanceof
MutableScan)) {
return call.result(call.target);
}
return null;{noformat}
But I might be missing a subtlety of how this bug could occur in other
situations with identity substitutions.
> Infinite Loop in SubstitutionVisitor.go
> ---------------------------------------
>
> Key: CALCITE-5254
> URL: https://issues.apache.org/jira/browse/CALCITE-5254
> Project: Calcite
> Issue Type: Bug
> Reporter: Steven Talbot
> Priority: Major
>
> Happens when you have a materialization "target" of an Aggregate/Scan
> attempting to substitute for an a "query" with a matching Scan.
> The following test should repro (in CustomMaterializedViewRecognitionRuleTest)
> {code:java}
> @Test void testNoInifiniteLoopOnAggregateScanMaterialization() {
> final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
> rootSchema.add("mv1", new AbstractTable() {
> @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
> return typeFactory.builder()
> .add("count", SqlTypeName.INTEGER)
> .build();
> }
> });
> final Frameworks.ConfigBuilder config = Frameworks.newConfigBuilder()
> .parserConfig(SqlParser.Config.DEFAULT)
> .defaultSchema(
> CalciteAssert.addSchema(rootSchema,
> CalciteAssert.SchemaSpec.SCOTT_WITH_TEMPORAL))
> .traitDefs((List<RelTraitDef>) null);
> final RelBuilder relBuilder = RelBuilder.create(config.build());
> final RelNode query = relBuilder.scan("EMP")
> .project(relBuilder.field("DEPTNO"))
> .aggregate(
> relBuilder.groupKey(0),
> relBuilder.aggregateCall(SqlStdOperatorTable.COUNT)
> )
> .build();
> final RelNode target = relBuilder.scan("EMP")
> .aggregate(relBuilder.groupKey(),
> relBuilder.aggregateCall(SqlStdOperatorTable.COUNT))
> .build();
> final RelNode replacement = relBuilder.scan("mv1").build();
> final RelOptMaterialization relOptMaterialization =
> new RelOptMaterialization(replacement,
> target, null, Lists.newArrayList("mv1"));
> final List<Pair<RelNode, List<RelOptMaterialization>>> relOptimized =
> RelOptMaterializations.useMaterializedViews(query,
> ImmutableList.of(relOptMaterialization),
> SubstitutionVisitor.DEFAULT_RULES);
> System.out.println("never ger here!");
> } {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)