[BugFix] Fix cte reuse plan extract error (backport #62784) (#63187)

Signed-off-by: Seaven <seaven_7@qq.com>
Co-authored-by: Seaven <seaven_7@qq.com>
This commit is contained in:
mergify[bot] 2025-09-17 09:37:19 +08:00 committed by GitHub
parent 71023642f7
commit fe9067d503
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 0 deletions

View File

@ -67,4 +67,9 @@ public class PhysicalNoCTEOperator extends PhysicalOperator {
public int hashCode() {
return Objects.hash(super.hashCode(), cteId);
}
@Override
public String toString() {
return "PhysicalNoCTEOperator[" + cteId + "]";
}
}

View File

@ -47,6 +47,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -193,6 +194,10 @@ public class EnforceAndCostTask extends OptimizerTask implements Cloneable {
// Successfully optimize all child group
if (curChildIndex == groupExpression.getInputs().size()) {
// check required CTE
if (!checkChildrenHasRequiredCTE(groupExpression, context.getRequiredProperty(), childrenOutputProperties)) {
break;
}
// before we compute the property, here need to make sure that the plan is legal
ChildOutputPropertyGuarantor childOutputPropertyGuarantor = new ChildOutputPropertyGuarantor(context,
groupExpression,
@ -232,6 +237,31 @@ public class EnforceAndCostTask extends OptimizerTask implements Cloneable {
groupExpression.getGroup().setCostLowerBound(context.getRequiredProperty(), cost);
}
private boolean checkChildrenHasRequiredCTE(GroupExpression groupExpression, PhysicalPropertySet requiredProperty,
List<PhysicalPropertySet> childrenOutputProperties) {
OperatorType operatorType = groupExpression.getOp().getOpType();
switch (operatorType) {
case PHYSICAL_CTE_ANCHOR:
case PHYSICAL_NO_CTE:
Set<Integer> requiredCTE = requiredProperty.getCteProperty().getCteIds();
Set<Integer> groupUseCTE = groupExpression.getGroup().getLogicalProperty().getUsedCTEs().getCteIds();
if (groupUseCTE.stream().anyMatch(requiredCTE::contains)) {
Set<Integer> childrenUseCteIds = childrenOutputProperties.stream()
.map(prop -> prop.getCteProperty().getCteIds())
.flatMap(Set::stream)
.collect(Collectors.toSet());
for (Integer cteId : requiredCTE) {
if (groupUseCTE.contains(cteId) && !childrenUseCteIds.contains(cteId)) {
return false;
}
}
}
return true;
default:
return true;
}
}
private boolean checkCTEPropertyValid(GroupExpression groupExpression, PhysicalPropertySet requiredPropertySet) {
OperatorType operatorType = groupExpression.getOp().getOpType();
CTEProperty property = requiredPropertySet.getCteProperty();