[Fix](Nereids) Check bound status in analyze straight after bounding (#18581)
Probleam: Dead loop cause of keep pushing analyze tasks into job stack. When doing analyze process and generate new operators, the same analyze rule would be pushed again, so it cause dead loop. And analyze process generate new operators when trying to bound order by key and aggregate function. Solve: We need to make it throw exception before complex analyze and rewrite process, so checking whether all expressions being bound should be done twice. One is done after bounding all expression, another is done after all analyze process in case of generate new expressions and new operators. Example: Cases were put in file: regression-test/suites/nereids_p0/except/test_bound_exception.groovy
This commit is contained in:
@ -24,6 +24,7 @@ import org.apache.doris.nereids.rules.analysis.AdjustAggregateNullableForEmptySe
|
||||
import org.apache.doris.nereids.rules.analysis.BindExpression;
|
||||
import org.apache.doris.nereids.rules.analysis.BindRelation;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckAnalysis;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckBound;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckPolicy;
|
||||
import org.apache.doris.nereids.rules.analysis.FillUpMissingSlots;
|
||||
import org.apache.doris.nereids.rules.analysis.NormalizeRepeat;
|
||||
@ -53,6 +54,9 @@ public class NereidsAnalyzer extends BatchRewriteJob {
|
||||
new UserAuthentication(),
|
||||
new BindExpression()
|
||||
),
|
||||
bottomUp(
|
||||
new CheckBound()
|
||||
),
|
||||
bottomUp(
|
||||
new ProjectToGlobalAggregate(),
|
||||
// this rule check's the logicalProject node's isDisinct property
|
||||
|
||||
@ -85,6 +85,7 @@ public enum RuleType {
|
||||
// check analysis rule
|
||||
CHECK_AGGREGATE_ANALYSIS(RuleTypeClass.CHECK),
|
||||
CHECK_ANALYSIS(RuleTypeClass.CHECK),
|
||||
CHECK_BOUND(RuleTypeClass.CHECK),
|
||||
CHECK_DATATYPES(RuleTypeClass.CHECK),
|
||||
|
||||
// rewrite rules
|
||||
|
||||
@ -78,17 +78,19 @@ public class CheckAnalysis implements AnalysisRuleFactory {
|
||||
.flatMap(Set::stream)
|
||||
.collect(Collectors.toSet());
|
||||
if (!unbounds.isEmpty()) {
|
||||
throw new AnalysisException(String.format("unbounded object %s.",
|
||||
StringUtils.join(unbounds.stream()
|
||||
.map(unbound -> {
|
||||
if (unbound instanceof UnboundSlot) {
|
||||
return ((UnboundSlot) unbound).toSql();
|
||||
} else if (unbound instanceof UnboundFunction) {
|
||||
return ((UnboundFunction) unbound).toSql();
|
||||
}
|
||||
return unbound.toString();
|
||||
})
|
||||
.collect(Collectors.toSet()), ", ")));
|
||||
throw new AnalysisException(String.format("unbounded object %s in %s clause.",
|
||||
StringUtils.join(unbounds.stream()
|
||||
.map(unbound -> {
|
||||
if (unbound instanceof UnboundSlot) {
|
||||
return ((UnboundSlot) unbound).toSql();
|
||||
} else if (unbound instanceof UnboundFunction) {
|
||||
return ((UnboundFunction) unbound).toSql();
|
||||
}
|
||||
return unbound.toString();
|
||||
})
|
||||
.collect(Collectors.toSet()), ", "),
|
||||
plan.getType().toString().substring("LOGICAL_".length())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,74 @@
|
||||
// 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.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.nereids.analyzer.Unbound;
|
||||
import org.apache.doris.nereids.analyzer.UnboundFunction;
|
||||
import org.apache.doris.nereids.analyzer.UnboundSlot;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Check bound rule to check semantic correct after bounding of expression by Nereids.
|
||||
* Also give operator information without LOGICAL_
|
||||
*/
|
||||
public class CheckBound implements AnalysisRuleFactory {
|
||||
|
||||
@Override
|
||||
public List<Rule> buildRules() {
|
||||
return ImmutableList.of(
|
||||
RuleType.CHECK_BOUND.build(
|
||||
any().then(plan -> {
|
||||
checkBound(plan);
|
||||
return null;
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void checkBound(Plan plan) {
|
||||
Set<Unbound> unbounds = plan.getExpressions().stream()
|
||||
.<Set<Unbound>>map(e -> e.collect(Unbound.class::isInstance))
|
||||
.flatMap(Set::stream)
|
||||
.collect(Collectors.toSet());
|
||||
if (!unbounds.isEmpty()) {
|
||||
throw new AnalysisException(String.format("unbounded object %s in %s clause.",
|
||||
StringUtils.join(unbounds.stream()
|
||||
.map(unbound -> {
|
||||
if (unbound instanceof UnboundSlot) {
|
||||
return ((UnboundSlot) unbound).toSql();
|
||||
} else if (unbound instanceof UnboundFunction) {
|
||||
return ((UnboundFunction) unbound).toSql();
|
||||
}
|
||||
return unbound.toString();
|
||||
})
|
||||
.collect(Collectors.toSet()), ", "),
|
||||
plan.getType().toString().substring("LOGICAL_".length())
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user