This is an automated email from the ASF dual-hosted git repository. starocean999 pushed a commit to branch dev_rec in repository https://gitbox.apache.org/repos/asf/doris.git
commit d23c1c2ae2797201efd1002e0056dd300ac44ca3 Author: lichi <[email protected]> AuthorDate: Mon Oct 13 16:03:36 2025 +0800 fix fe plan --- .../glue/translator/PhysicalPlanTranslator.java | 13 ++- .../properties/ChildOutputPropertyDeriver.java | 10 +- .../org/apache/doris/nereids/rules/RuleSet.java | 2 + .../org/apache/doris/nereids/rules/RuleType.java | 1 + .../doris/nereids/rules/analysis/AnalyzeCTE.java | 31 +++++- ...eChildToPhysicalRecursiveCteRecursiveChild.java | 36 +++++++ .../doris/nereids/stats/StatsCalculator.java | 14 +++ .../trees/copier/LogicalPlanDeepCopier.java | 8 ++ .../apache/doris/nereids/trees/plans/PlanType.java | 2 + .../logical/LogicalRecursiveCteRecursiveChild.java | 103 +++++++++++++++++++ .../PhysicalRecursiveCteRecursiveChild.java | 110 +++++++++++++++++++++ .../nereids/trees/plans/visitor/PlanVisitor.java | 12 +++ .../apache/doris/planner/RecursiveCteScanNode.java | 6 +- .../doris/qe/runtime/ThriftPlansBuilder.java | 2 +- 14 files changed, 343 insertions(+), 7 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java index 38e7a10827a..974d63ca138 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java @@ -157,6 +157,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalQuickSort; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteScan; import org.apache.doris.nereids.trees.plans.physical.PhysicalRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalRepeat; @@ -1079,9 +1080,10 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla PlanTranslatorContext context) { TableIf table = recursiveCteScan.getTable(); List<Slot> slots = ImmutableList.copyOf(recursiveCteScan.getOutput()); - TupleDescriptor tupleDescriptor = generateTupleDesc(slots, table, context); + TupleDescriptor tupleDescriptor = generateTupleDesc(slots, null, context); - RecursiveCteScanNode scanNode = new RecursiveCteScanNode(context.nextPlanNodeId(), tupleDescriptor); + RecursiveCteScanNode scanNode = new RecursiveCteScanNode(table != null ? table.getName() : "", + context.nextPlanNodeId(), tupleDescriptor); scanNode.setNereidsId(recursiveCteScan.getId()); context.getNereidsIdToPlanNodeIdMap().put(recursiveCteScan.getId(), scanNode.getId()); Utils.execWithUncheckedException(scanNode::initScanRangeLocations); @@ -2341,6 +2343,13 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla return recursiveCteFragment; } + @Override + public PlanFragment visitPhysicalRecursiveCteRecursiveChild( + PhysicalRecursiveCteRecursiveChild<? extends Plan> recursiveChild, + PlanTranslatorContext context) { + return recursiveChild.child().accept(this, context); + } + /** * Returns a new fragment with a UnionNode as its root. The data partition of the * returned fragment and how the data of the child fragments is consumed depends on the diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java index 0751f14b715..56433c82d33 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/ChildOutputPropertyDeriver.java @@ -53,6 +53,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalOneRowRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalPartitionTopN; import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteScan; import org.apache.doris.nereids.trees.plans.physical.PhysicalRepeat; import org.apache.doris.nereids.trees.plans.physical.PhysicalSetOperation; @@ -151,7 +152,7 @@ public class ChildOutputPropertyDeriver extends PlanVisitor<PhysicalProperties, @Override public PhysicalProperties visitPhysicalRecursiveCteScan(PhysicalRecursiveCteScan cteScan, PlanContext context) { - return PhysicalProperties.MUST_SHUFFLE; + return PhysicalProperties.ANY; } /** @@ -475,6 +476,13 @@ public class ChildOutputPropertyDeriver extends PlanVisitor<PhysicalProperties, return PhysicalProperties.GATHER; } + @Override + public PhysicalProperties visitPhysicalRecursiveCteRecursiveChild( + PhysicalRecursiveCteRecursiveChild<? extends Plan> recursiveChild, + PlanContext context) { + return PhysicalProperties.MUST_SHUFFLE; + } + @Override public PhysicalProperties visitPhysicalUnion(PhysicalUnion union, PlanContext context) { if (union.getConstantExprsList().isEmpty()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java index 122dbee03ef..62a5d7702c3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java @@ -80,6 +80,7 @@ import org.apache.doris.nereids.rules.implementation.LogicalOlapTableSinkToPhysi import org.apache.doris.nereids.rules.implementation.LogicalOneRowRelationToPhysicalOneRowRelation; import org.apache.doris.nereids.rules.implementation.LogicalPartitionTopNToPhysicalPartitionTopN; import org.apache.doris.nereids.rules.implementation.LogicalProjectToPhysicalProject; +import org.apache.doris.nereids.rules.implementation.LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.rules.implementation.LogicalRecursiveCteScanToPhysicalRecursiveCteScan; import org.apache.doris.nereids.rules.implementation.LogicalRecursiveCteToPhysicalRecursiveCte; import org.apache.doris.nereids.rules.implementation.LogicalRepeatToPhysicalRepeat; @@ -213,6 +214,7 @@ public class RuleSet { .add(SplitAggMultiPhase.INSTANCE) .add(SplitAggMultiPhaseWithoutGbyKey.INSTANCE) .add(new LogicalRecursiveCteToPhysicalRecursiveCte()) + .add(new LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild()) .add(new LogicalUnionToPhysicalUnion()) .add(new LogicalExceptToPhysicalExcept()) .add(new LogicalIntersectToPhysicalIntersect()) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java index c13607a838d..75550513068 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleType.java @@ -519,6 +519,7 @@ public enum RuleType { TWO_PHASE_AGGREGATE_WITH_DISTINCT(RuleTypeClass.IMPLEMENTATION), LOGICAL_UNION_TO_PHYSICAL_UNION(RuleTypeClass.IMPLEMENTATION), LOGICAL_RECURSIVE_CTE_TO_PHYSICAL_RECURSIVE_CTE(RuleTypeClass.IMPLEMENTATION), + LOGICAL_RECURSIVE_CTE_RECURSIVE_CHILD_TO_PHYSICAL_RECURSIVE_CTE_RECURSIVE_CHILD(RuleTypeClass.IMPLEMENTATION), LOGICAL_EXCEPT_TO_PHYSICAL_EXCEPT(RuleTypeClass.IMPLEMENTATION), LOGICAL_INTERSECT_TO_PHYSICAL_INTERSECT(RuleTypeClass.IMPLEMENTATION), LOGICAL_GENERATE_TO_PHYSICAL_GENERATE(RuleTypeClass.IMPLEMENTATION), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java index a6259f0b24c..906d572c6c1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java @@ -23,11 +23,13 @@ import org.apache.doris.nereids.CascadesContext; 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.expressions.Alias; import org.apache.doris.nereids.trees.expressions.CTEId; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator; +import org.apache.doris.nereids.trees.expressions.functions.scalar.Nullable; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.algebra.SetOperation; import org.apache.doris.nereids.trees.plans.logical.LogicalCTE; @@ -36,9 +38,11 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalCTEProducer; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias; import org.apache.doris.nereids.trees.plans.logical.LogicalUnion; import org.apache.doris.nereids.trees.plans.logical.ProjectProcessor; +import org.apache.doris.nereids.types.DataType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; @@ -146,6 +150,11 @@ public class AnalyzeCTE extends OneAnalysisRuleFactory { }); cascadesContext.addPlanProcesses(innerAnchorCascadesCtx.getPlanProcesses()); LogicalPlan analyzedAnchorChild = (LogicalPlan) innerAnchorCascadesCtx.getRewritePlan(); + List<NamedExpression> anchorNullableOutputs = new ArrayList<>(analyzedAnchorChild.getOutput().size()); + for (Slot slot : analyzedAnchorChild.getOutput()) { + anchorNullableOutputs.add(new Alias(new Nullable(slot), slot.getName())); + } + analyzedAnchorChild = new LogicalProject<>(anchorNullableOutputs, analyzedAnchorChild); checkColumnAlias(aliasQuery, analyzedAnchorChild.getOutput()); // analyze recursive child @@ -158,9 +167,29 @@ public class AnalyzeCTE extends OneAnalysisRuleFactory { }); cascadesContext.addPlanProcesses(innerRecursiveCascadesCtx.getPlanProcesses()); LogicalPlan analyzedRecursiveChild = (LogicalPlan) innerRecursiveCascadesCtx.getRewritePlan(); - LogicalUnion logicalUnion = (LogicalUnion) parsedCtePlan; + List<DataType> anchorChildOutputTypes = new ArrayList<>(analyzedAnchorChild.getOutput().size()); + for (Slot slot : analyzedAnchorChild.getOutput()) { + anchorChildOutputTypes.add(slot.getDataType()); + } + List<Slot> recursiveChildOutputs = analyzedRecursiveChild.getOutput(); + for (int i = 0; i < recursiveChildOutputs.size(); ++i) { + if (recursiveChildOutputs.get(i).getDataType() != anchorChildOutputTypes.get(i)) { + throw new AnalysisException(String.format("recursive child's %d column's datatype in select list %s " + + "is different from anchor child's output datatype %s, please add cast manually " + + "to get expect datatype", + i + 1, recursiveChildOutputs.get(i).getDataType(), anchorChildOutputTypes.get(i))); + } + } + + List<NamedExpression> recursiveNullableOutputs = new ArrayList<>(analyzedRecursiveChild.getOutput().size()); + for (Slot slot : analyzedRecursiveChild.getOutput()) { + recursiveNullableOutputs.add(new Alias(new Nullable(slot), slot.getName())); + } + analyzedRecursiveChild = new LogicalProject<>(recursiveNullableOutputs, analyzedRecursiveChild); + analyzedRecursiveChild = new LogicalRecursiveCteRecursiveChild<>(analyzedRecursiveChild); // create LogicalRecursiveCte + LogicalUnion logicalUnion = (LogicalUnion) parsedCtePlan; LogicalRecursiveCte analyzedCtePlan = new LogicalRecursiveCte( logicalUnion.getQualifier() == SetOperation.Qualifier.ALL, ImmutableList.of(analyzedAnchorChild, analyzedRecursiveChild)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild.java new file mode 100644 index 00000000000..2923924a6ad --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild.java @@ -0,0 +1,36 @@ +// 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.implementation; + +import org.apache.doris.nereids.rules.Rule; +import org.apache.doris.nereids.rules.RuleType; +import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteRecursiveChild; + +/** + * Implementation rule that convert logical recursive cte's recursive child to physical recursive child. + */ +public class LogicalRecursiveCteRecursiveChildToPhysicalRecursiveCteRecursiveChild + extends OneImplementationRuleFactory { + @Override + public Rule build() { + return logicalRecursiveCteRecursiveChild().then(recursiveCte -> new PhysicalRecursiveCteRecursiveChild( + recursiveCte.getLogicalProperties(), + recursiveCte.child())) + .toRule(RuleType.LOGICAL_RECURSIVE_CTE_RECURSIVE_CHILD_TO_PHYSICAL_RECURSIVE_CTE_RECURSIVE_CHILD); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/StatsCalculator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/StatsCalculator.java index 9ddcc7e2e40..930674b873b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/StatsCalculator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/StatsCalculator.java @@ -92,6 +92,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalOneRowRelation; import org.apache.doris.nereids.trees.plans.logical.LogicalPartitionTopN; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCteScan; import org.apache.doris.nereids.trees.plans.logical.LogicalRepeat; import org.apache.doris.nereids.trees.plans.logical.LogicalSchemaScan; @@ -127,6 +128,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalPartitionTopN; import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalQuickSort; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteScan; import org.apache.doris.nereids.trees.plans.physical.PhysicalRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalRepeat; @@ -931,6 +933,12 @@ public class StatsCalculator extends DefaultPlanVisitor<Statistics, Void> { .stream().map(Group::getStatistics).collect(Collectors.toList())); } + @Override + public Statistics visitLogicalRecursiveCteRecursiveChild(LogicalRecursiveCteRecursiveChild recursiveChild, + Void context) { + return groupExpression.childStatistics(0); + } + @Override public Statistics visitLogicalUnion( LogicalUnion union, Void context) { @@ -1113,6 +1121,12 @@ public class StatsCalculator extends DefaultPlanVisitor<Statistics, Void> { .stream().map(Group::getStatistics).collect(Collectors.toList())); } + @Override + public Statistics visitPhysicalRecursiveCteRecursiveChild(PhysicalRecursiveCteRecursiveChild recursiveChild, + Void context) { + return groupExpression.childStatistics(0); + } + @Override public Statistics visitPhysicalUnion(PhysicalUnion union, Void context) { return computeUnion(union, groupExpression.children() diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java index 739047f4a77..98c3ec2ef41 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/copier/LogicalPlanDeepCopier.java @@ -54,6 +54,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalPartitionTopN; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.logical.LogicalRelation; import org.apache.doris.nereids.trees.plans.logical.LogicalRepeat; import org.apache.doris.nereids.trees.plans.logical.LogicalSink; @@ -371,6 +372,13 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext return new LogicalRecursiveCte(recursiveCte.isUnionAll(), outputs, childrenOutputs, children); } + @Override + public Plan visitLogicalRecursiveCteRecursiveChild(LogicalRecursiveCteRecursiveChild<? extends Plan> recursiveChild, + DeepCopierContext context) { + Plan child = recursiveChild.child().accept(this, context); + return new LogicalRecursiveCteRecursiveChild<>(child); + } + @Override public Plan visitLogicalExcept(LogicalExcept except, DeepCopierContext context) { List<Plan> children = except.children().stream() diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java index fe7661dbc4d..03df1c26fb7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanType.java @@ -84,6 +84,7 @@ public enum PlanType { LOGICAL_PROJECT, LOGICAL_QUALIFY, LOGICAL_RECURSIVE_CTE, + LOGICAL_RECURSIVE_CTE_RECURSIVE_CHILD, LOGICAL_RECURSIVE_CTE_SCAN, LOGICAL_REPEAT, LOGICAL_SELECT_HINT, @@ -127,6 +128,7 @@ public enum PlanType { PHYSICAL_CTE_PRODUCER, PHYSICAL_CTE_ANCHOR, PHYSICAL_RECURSIVE_CTE, + PHYSICAL_RECURSIVE_CTE_RECURSIVE_CHILD, PHYSICAL_DISTRIBUTE, PHYSICAL_EXCEPT, PHYSICAL_FILTER, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalRecursiveCteRecursiveChild.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalRecursiveCteRecursiveChild.java new file mode 100644 index 00000000000..f73323b50bb --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalRecursiveCteRecursiveChild.java @@ -0,0 +1,103 @@ +// 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.trees.plans.logical; + +import org.apache.doris.nereids.memo.GroupExpression; +import org.apache.doris.nereids.properties.DataTrait; +import org.apache.doris.nereids.properties.LogicalProperties; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; + +import com.google.common.collect.ImmutableList; + +import java.util.List; +import java.util.Optional; + +/** + * LogicalRecursiveCteRecursiveChild is sentinel plan for must_shuffle + */ +public class LogicalRecursiveCteRecursiveChild<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_TYPE> { + + public LogicalRecursiveCteRecursiveChild(CHILD_TYPE child) { + this(Optional.empty(), Optional.empty(), child); + } + + public LogicalRecursiveCteRecursiveChild(Optional<GroupExpression> groupExpression, + Optional<LogicalProperties> logicalProperties, CHILD_TYPE child) { + this(groupExpression, logicalProperties, ImmutableList.of(child)); + } + + public LogicalRecursiveCteRecursiveChild(Optional<GroupExpression> groupExpression, + Optional<LogicalProperties> logicalProperties, List<Plan> child) { + super(PlanType.LOGICAL_RECURSIVE_CTE_RECURSIVE_CHILD, groupExpression, logicalProperties, child); + } + + @Override + public Plan withChildren(List<Plan> children) { + return new LogicalRecursiveCteRecursiveChild<>(Optional.empty(), Optional.empty(), children); + } + + @Override + public <R, C> R accept(PlanVisitor<R, C> visitor, C context) { + return visitor.visitLogicalRecursiveCteRecursiveChild(this, context); + } + + @Override + public List<? extends Expression> getExpressions() { + return ImmutableList.of(); + } + + @Override + public Plan withGroupExpression(Optional<GroupExpression> groupExpression) { + return new LogicalRecursiveCteRecursiveChild<>(groupExpression, Optional.of(getLogicalProperties()), children); + } + + @Override + public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression> groupExpression, + Optional<LogicalProperties> logicalProperties, List<Plan> children) { + return new LogicalRecursiveCteRecursiveChild<>(groupExpression, logicalProperties, children); + } + + @Override + public void computeUnique(DataTrait.Builder builder) { + + } + + @Override + public void computeUniform(DataTrait.Builder builder) { + + } + + @Override + public void computeEqualSet(DataTrait.Builder builder) { + + } + + @Override + public void computeFd(DataTrait.Builder builder) { + + } + + @Override + public List<Slot> computeOutput() { + return child().getOutput(); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalRecursiveCteRecursiveChild.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalRecursiveCteRecursiveChild.java new file mode 100644 index 00000000000..5f598d8feac --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalRecursiveCteRecursiveChild.java @@ -0,0 +1,110 @@ +// 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.trees.plans.physical; + +import org.apache.doris.nereids.memo.GroupExpression; +import org.apache.doris.nereids.properties.DataTrait; +import org.apache.doris.nereids.properties.LogicalProperties; +import org.apache.doris.nereids.properties.PhysicalProperties; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.statistics.Statistics; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +/** + * PhysicalRecursiveCteRecursiveChild is sentinel plan for must_shuffle + */ +public class PhysicalRecursiveCteRecursiveChild<CHILD_TYPE extends Plan> extends PhysicalUnary<CHILD_TYPE> { + public PhysicalRecursiveCteRecursiveChild(LogicalProperties logicalProperties, CHILD_TYPE child) { + this(Optional.empty(), logicalProperties, child); + } + + public PhysicalRecursiveCteRecursiveChild(Optional<GroupExpression> groupExpression, + LogicalProperties logicalProperties, CHILD_TYPE child) { + this(groupExpression, logicalProperties, PhysicalProperties.ANY, null, child); + } + + public PhysicalRecursiveCteRecursiveChild(Optional<GroupExpression> groupExpression, + LogicalProperties logicalProperties, @Nullable PhysicalProperties physicalProperties, Statistics statistics, + CHILD_TYPE child) { + super(PlanType.PHYSICAL_RECURSIVE_CTE_RECURSIVE_CHILD, groupExpression, logicalProperties, physicalProperties, + statistics, child); + } + + @Override + public Plan withChildren(List<Plan> children) { + Preconditions.checkArgument(children.size() == 1); + return new PhysicalRecursiveCteRecursiveChild<>(groupExpression, getLogicalProperties(), children.get(0)); + } + + @Override + public <R, C> R accept(PlanVisitor<R, C> visitor, C context) { + return visitor.visitPhysicalRecursiveCteRecursiveChild(this, context); + } + + @Override + public List<? extends Expression> getExpressions() { + return ImmutableList.of(); + } + + @Override + public Plan withGroupExpression(Optional<GroupExpression> groupExpression) { + return new PhysicalRecursiveCteRecursiveChild<>(groupExpression, getLogicalProperties(), child()); + } + + @Override + public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression> groupExpression, + Optional<LogicalProperties> logicalProperties, List<Plan> children) { + Preconditions.checkArgument(children.size() == 1); + return new PhysicalRecursiveCteRecursiveChild<>(groupExpression, logicalProperties.get(), child()); + } + + @Override + public void computeUnique(DataTrait.Builder builder) { + + } + + @Override + public void computeUniform(DataTrait.Builder builder) { + + } + + @Override + public void computeEqualSet(DataTrait.Builder builder) { + + } + + @Override + public void computeFd(DataTrait.Builder builder) { + + } + + @Override + public PhysicalPlan withPhysicalPropertiesAndStats(PhysicalProperties physicalProperties, Statistics statistics) { + return new PhysicalRecursiveCteRecursiveChild<>(groupExpression, getLogicalProperties(), physicalProperties, + statistics, child()); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/PlanVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/PlanVisitor.java index 66918845e00..5b0067bbd7a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/PlanVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/PlanVisitor.java @@ -45,6 +45,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalPreFilter; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.trees.plans.logical.LogicalQualify; import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.logical.LogicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.logical.LogicalRelation; import org.apache.doris.nereids.trees.plans.logical.LogicalRepeat; import org.apache.doris.nereids.trees.plans.logical.LogicalSelectHint; @@ -80,6 +81,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalPartitionTopN; import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalQuickSort; import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCte; +import org.apache.doris.nereids.trees.plans.physical.PhysicalRecursiveCteRecursiveChild; import org.apache.doris.nereids.trees.plans.physical.PhysicalRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalRepeat; import org.apache.doris.nereids.trees.plans.physical.PhysicalSetOperation; @@ -217,6 +219,11 @@ public abstract class PlanVisitor<R, C> implements CommandVisitor<R, C>, Relatio return visit(recursiveCte, context); } + public R visitLogicalRecursiveCteRecursiveChild(LogicalRecursiveCteRecursiveChild<? extends Plan> recursiveChild, + C context) { + return visit(recursiveChild, context); + } + public R visitLogicalLimit(LogicalLimit<? extends Plan> limit, C context) { return visit(limit, context); } @@ -386,6 +393,11 @@ public abstract class PlanVisitor<R, C> implements CommandVisitor<R, C>, Relatio return visit(recursiveCte, context); } + public R visitPhysicalRecursiveCteRecursiveChild(PhysicalRecursiveCteRecursiveChild<? extends Plan> recursiveChild, + C context) { + return visit(recursiveChild, context); + } + public R visitAbstractPhysicalSort(AbstractPhysicalSort<? extends Plan> sort, C context) { return visit(sort, context); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java index 35065314bab..eb63ba6fcb7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java @@ -38,9 +38,11 @@ import java.util.List; // Full scan of recursive cte temp table public class RecursiveCteScanNode extends ScanNode { + private final String recursiveCteName; - public RecursiveCteScanNode(PlanNodeId id, TupleDescriptor desc) { + public RecursiveCteScanNode(String recursiveCteName, PlanNodeId id, TupleDescriptor desc) { super(id, desc, "RECURSIVE_CTE_SCAN", StatisticalType.CTE_SCAN_NODE); + this.recursiveCteName = recursiveCteName; } public void initScanRangeLocations() throws UserException { @@ -91,7 +93,7 @@ public class RecursiveCteScanNode extends ScanNode { @Override public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { StringBuilder output = new StringBuilder(); - output.append(prefix).append("Recursive Cte: ").append(getTableIf().getName()).append("\n"); + output.append(prefix).append("Recursive Cte: ").append(recursiveCteName).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/runtime/ThriftPlansBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/qe/runtime/ThriftPlansBuilder.java index 13034b91897..1657ef7fcef 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/runtime/ThriftPlansBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/runtime/ThriftPlansBuilder.java @@ -633,7 +633,7 @@ public class ThriftPlansBuilder { List<TRecCTETarget> targets = new ArrayList<>(); List<TRecCTEResetInfo> fragmentsToReset = new ArrayList<>(); - // PhysicalPlanTranslator will swap recursiveCteNodes's child fragment, + // PhysicalPlanTranslator will swap recursiveCteNode's child fragment, // so we get recursive one by 1st child List<PlanFragment> childFragments = new ArrayList<>(); planFragment.getChild(0).collectAll(PlanFragment.class::isInstance, childFragments); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
