This is an automated email from the ASF dual-hosted git repository.
morrySnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 153dfb5f586 [fix](data traits) Fix data trait propagation for logical
CTE anchors (#64921)
153dfb5f586 is described below
commit 153dfb5f586b7d71f6ab254fd7ebfebc0eb9a94f
Author: feiniaofeiafei <[email protected]>
AuthorDate: Tue Jun 30 14:40:27 2026 +0800
[fix](data traits) Fix data trait propagation for logical CTE anchors
(#64921)
### What problem does this PR solve?
`LogicalCTEAnchor` previously implemented `PropagateFuncDeps`. Since it
is a binary plan node, the default implementation merged data traits
from both the CTE producer and the right child.
However, a logical CTE anchor exposes only the output of its right
child. Merging the producer's data traits could therefore introduce
traits associated with slots that are not part of the anchor output,
leading to incorrect logical properties.
This change makes `LogicalCTEAnchor` propagate data traits exclusively
from its right child. It also enables and extends the CTE unit test to
keep the CTE anchor from being inlined and verify the propagated traits.
---
.../trees/plans/logical/LogicalCTEAnchor.java | 34 ++++++++++++++++++--
.../trees/plans/physical/PhysicalCTEAnchor.java | 34 ++++++++++++++++++--
.../doris/nereids/properties/DataTraitTest.java | 37 ++++++++++++++++------
3 files changed, 90 insertions(+), 15 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTEAnchor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTEAnchor.java
index 23cd6181345..9e075bb2580 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTEAnchor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCTEAnchor.java
@@ -18,6 +18,7 @@
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.CTEId;
import org.apache.doris.nereids.trees.expressions.Expression;
@@ -25,7 +26,6 @@ import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.AbstractPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
-import org.apache.doris.nereids.trees.plans.PropagateFuncDeps;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
import org.apache.doris.nereids.util.Utils;
@@ -39,8 +39,7 @@ import java.util.Optional;
* LogicalCTEAnchor
*/
public class LogicalCTEAnchor<LEFT_CHILD_TYPE extends Plan,
- RIGHT_CHILD_TYPE extends Plan> extends LogicalBinary<LEFT_CHILD_TYPE,
RIGHT_CHILD_TYPE> implements
- PropagateFuncDeps {
+ RIGHT_CHILD_TYPE extends Plan> extends LogicalBinary<LEFT_CHILD_TYPE,
RIGHT_CHILD_TYPE> {
private final CTEId cteId;
@@ -114,4 +113,33 @@ public class LogicalCTEAnchor<LEFT_CHILD_TYPE extends Plan,
public int hashCode() {
return Objects.hash(cteId);
}
+
+ @Override
+ public DataTrait computeDataTrait() {
+ return right().getLogicalProperties().getTrait();
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeUnique(DataTrait.Builder builder) {
+ builder.addUniqueSlot(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeUniform(DataTrait.Builder builder) {
+ builder.addUniformSlot(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeEqualSet(DataTrait.Builder builder) {
+ builder.addEqualSet(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeFd(DataTrait.Builder builder) {
+ builder.addFuncDepsDG(right().getLogicalProperties().getTrait());
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCTEAnchor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCTEAnchor.java
index 8e494bd66dc..8a0dcf6f4a4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCTEAnchor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalCTEAnchor.java
@@ -18,6 +18,7 @@
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.CTEId;
@@ -26,7 +27,6 @@ import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.plans.AbstractPlan;
import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
-import org.apache.doris.nereids.trees.plans.PropagateFuncDeps;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
import org.apache.doris.nereids.util.Utils;
import org.apache.doris.statistics.Statistics;
@@ -44,8 +44,7 @@ import java.util.Optional;
public class PhysicalCTEAnchor<
LEFT_CHILD_TYPE extends Plan,
RIGHT_CHILD_TYPE extends Plan>
- extends PhysicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements
- PropagateFuncDeps {
+ extends PhysicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
private final CTEId cteId;
public PhysicalCTEAnchor(CTEId cteId, LogicalProperties logicalProperties,
@@ -146,4 +145,33 @@ public class PhysicalCTEAnchor<
return new PhysicalCTEAnchor<>(cteId, groupExpression, null,
physicalProperties,
statistics, child(0), child(1));
}
+
+ @Override
+ public DataTrait computeDataTrait() {
+ return right().getLogicalProperties().getTrait();
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeUnique(DataTrait.Builder builder) {
+ builder.addUniqueSlot(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeUniform(DataTrait.Builder builder) {
+ builder.addUniformSlot(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeEqualSet(DataTrait.Builder builder) {
+ builder.addEqualSet(right().getLogicalProperties().getTrait());
+ }
+
+ // This function is useless, actually.
+ @Override
+ public void computeFd(DataTrait.Builder builder) {
+ builder.addFuncDepsDG(right().getLogicalProperties().getTrait());
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/DataTraitTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/DataTraitTest.java
index 5ca6450d883..6647522c269 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/DataTraitTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/DataTraitTest.java
@@ -21,14 +21,15 @@ import
org.apache.doris.nereids.properties.DataTrait.Builder;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SlotReference;
import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalCTEAnchor;
import org.apache.doris.nereids.trees.plans.logical.LogicalPartitionTopN;
+import org.apache.doris.nereids.trees.plans.physical.PhysicalCTEAnchor;
import org.apache.doris.nereids.types.IntegerType;
import org.apache.doris.nereids.util.PlanChecker;
import org.apache.doris.utframe.TestWithFeService;
import com.google.common.collect.ImmutableSet;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class DataTraitTest extends TestWithFeService {
@@ -333,16 +334,34 @@ class DataTraitTest extends TestWithFeService {
.getTrait().isUniqueAndNotNull(plan.getOutput().get(0)));
}
- @Disabled
@Test
void testCTE() {
- Plan plan = PlanChecker.from(connectContext)
- .analyze("with t as (select * from agg) select id from t where
id = 1")
- .getPlan();
- System.out.println(plan.treeString());
- System.out.println(plan.getLogicalProperties().getTrait());
- Assertions.assertTrue(plan.getLogicalProperties()
- .getTrait().isUniqueAndNotNull(plan.getOutput().get(0)));
+ int oldInlineCTEReferencedThreshold =
connectContext.getSessionVariable().inlineCTEReferencedThreshold;
+ connectContext.getSessionVariable().inlineCTEReferencedThreshold = 0;
+ try {
+ Plan plan = PlanChecker.from(connectContext)
+ .analyze("with t as (select * from agg) select id from t
where id = 1")
+ .rewrite()
+ .getPlan();
+ Assertions.assertInstanceOf(LogicalCTEAnchor.class, plan);
+ Assertions.assertTrue(plan.getLogicalProperties()
+ .getTrait().isUniformAndNotNull(plan.getOutput().get(0)));
+ Assertions.assertEquals(plan.getLogicalProperties().getTrait(),
+ plan.child(1).getLogicalProperties().getTrait());
+
+ Plan physicalPlan = PlanChecker.from(connectContext)
+ .analyze("with t as (select * from agg) select id from t
where id = 1")
+ .rewrite()
+ .optimize()
+ .getBestPlanTree();
+ Assertions.assertInstanceOf(PhysicalCTEAnchor.class, physicalPlan);
+ Assertions.assertTrue(physicalPlan.getLogicalProperties()
+
.getTrait().isUniformAndNotNull(physicalPlan.getOutput().get(0)));
+
Assertions.assertEquals(physicalPlan.getLogicalProperties().getTrait(),
+ physicalPlan.child(1).getLogicalProperties().getTrait());
+ } finally {
+ connectContext.getSessionVariable().inlineCTEReferencedThreshold =
oldInlineCTEReferencedThreshold;
+ }
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]