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 5fad4f4c7b [feature](Nereids) replace order by keys by child output if 
possible (#14108)
5fad4f4c7b is described below

commit 5fad4f4c7b78ee8a7ca38b82900fb08d9782175c
Author: morrySnow <[email protected]>
AuthorDate: Fri Nov 11 13:34:29 2022 +0800

    [feature](Nereids) replace order by keys by child output if possible 
(#14108)
    
    To support query like that:
    SELECT c1 + 1 as a, sum(c2) FROM t GROUP BY c1 + 1 ORDER BY c1 + 1
    
    After rewrite, plan will equal to
    SELECT c1 + 1 as a, sum(c2) FROM t GROUP BY c1 + 1 ORDER BY a
---
 .../doris/nereids/jobs/batch/AnalyzeRulesJob.java  |  4 +-
 .../org/apache/doris/nereids/rules/RuleType.java   |  9 +-
 .../nereids/rules/analysis/FillUpMissingSlots.java | 64 ++++++++------
 .../analysis/ReplaceExpressionByChildOutput.java   | 99 ++++++++++++++++++++++
 .../analysis}/AnalyzeFunctionTest.java             |  3 +-
 .../analysis}/AnalyzeSubQueryTest.java             |  7 +-
 .../analysis}/AnalyzeWhereSubqueryTest.java        |  6 +-
 .../analysis}/FillUpMissingSlotsTest.java          | 35 ++++----
 .../{util => rules/analysis}/RegisterCTETest.java  |  7 +-
 .../ReplaceExpressionByChildOutputTest.java        | 97 +++++++++++++++++++++
 10 files changed, 274 insertions(+), 57 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
index db7528d4bc..a7a48738ca 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/AnalyzeRulesJob.java
@@ -24,6 +24,7 @@ import 
org.apache.doris.nereids.rules.analysis.BindSlotReference;
 import org.apache.doris.nereids.rules.analysis.FillUpMissingSlots;
 import org.apache.doris.nereids.rules.analysis.ProjectToGlobalAggregate;
 import org.apache.doris.nereids.rules.analysis.RegisterCTE;
+import org.apache.doris.nereids.rules.analysis.ReplaceExpressionByChildOutput;
 import org.apache.doris.nereids.rules.analysis.Scope;
 import org.apache.doris.nereids.rules.analysis.UserAuthentication;
 
@@ -52,7 +53,8 @@ public class AnalyzeRulesJob extends BatchRulesJob {
                         new UserAuthentication(),
                         new BindSlotReference(scope),
                         new BindFunction(),
-                        new ProjectToGlobalAggregate()
+                        new ProjectToGlobalAggregate(),
+                        new ReplaceExpressionByChildOutput()
                 )),
                 topDownBatch(ImmutableList.of(
                         new FillUpMissingSlots()
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 89a00279e6..14b5b2a263 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
@@ -46,9 +46,12 @@ public enum RuleType {
     BINDING_FILTER_FUNCTION(RuleTypeClass.REWRITE),
     BINDING_HAVING_FUNCTION(RuleTypeClass.REWRITE),
     BINDING_SORT_FUNCTION(RuleTypeClass.REWRITE),
-    FILL_UP_HAVING_AGGREGATE_FUNCTIONS(RuleTypeClass.REWRITE),
-    FILL_UP_SORT_AGGREGATE_FUNCTIONS(RuleTypeClass.REWRITE),
-    FILL_UP_SORT_HAVING_AGGREGATE_FUNCTIONS(RuleTypeClass.REWRITE),
+
+    REPLACE_SORT_EXPRESSION_BY_CHILD_OUTPUT(RuleTypeClass.REWRITE),
+
+    FILL_UP_HAVING_AGGREGATE(RuleTypeClass.REWRITE),
+    FILL_UP_SORT_AGGREGATE(RuleTypeClass.REWRITE),
+    FILL_UP_SORT_HAVING_AGGREGATE(RuleTypeClass.REWRITE),
     FILL_UP_SORT_PROJECT(RuleTypeClass.REWRITE),
 
     RESOLVE_PROJECT_ALIAS(RuleTypeClass.REWRITE),
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlots.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlots.java
index 9215363e95..fc385587dc 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlots.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlots.java
@@ -32,6 +32,7 @@ import org.apache.doris.nereids.trees.plans.GroupPlan;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
 import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
+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.LogicalSort;
 import org.apache.doris.nereids.util.ExpressionUtils;
@@ -50,15 +51,34 @@ import java.util.stream.Collectors;
 
 /**
  * Resolve having clause to the aggregation.
+ * need Top to Down to traverse plan,
+ * because we need to process FILL_UP_SORT_HAVING_AGGREGATE before 
FILL_UP_HAVING_AGGREGATE.
  */
 public class FillUpMissingSlots implements AnalysisRuleFactory {
     @Override
     public List<Rule> buildRules() {
         return ImmutableList.of(
-                RuleType.FILL_UP_SORT_AGGREGATE_FUNCTIONS.build(
+                RuleType.FILL_UP_SORT_PROJECT.build(
+                        logicalSort(logicalProject())
+                                .when(this::checkSort)
+                                .then(sort -> {
+                                    final Builder<NamedExpression> 
projectionsBuilder = ImmutableList.builder();
+                                    
projectionsBuilder.addAll(sort.child().getProjects());
+                                    Set<Slot> notExistedInProject = 
sort.getExpressions().stream()
+                                            .map(Expression::getInputSlots)
+                                            .flatMap(Set::stream)
+                                            .filter(s -> 
!sort.child().getOutputSet().contains(s))
+                                            .collect(Collectors.toSet());
+                                    
projectionsBuilder.addAll(notExistedInProject);
+                                    return new 
LogicalProject(sort.child().getOutput(),
+                                            new 
LogicalSort<>(sort.getOrderKeys(),
+                                                    new 
LogicalProject<>(projectionsBuilder.build(),
+                                                            
sort.child().child())));
+                                })
+                ),
+                RuleType.FILL_UP_SORT_AGGREGATE.build(
                         logicalSort(logicalAggregate())
-                                .when(sort -> sort.getExpressions().stream()
-                                        .anyMatch(e -> 
e.containsType(AggregateFunction.class)))
+                                .when(this::checkSort)
                                 .then(sort -> {
                                     LogicalAggregate<GroupPlan> aggregate = 
sort.child();
                                     Resolver resolver = new 
Resolver(aggregate);
@@ -74,10 +94,9 @@ public class FillUpMissingSlots implements 
AnalysisRuleFactory {
                                     });
                                 })
                 ),
-                RuleType.FILL_UP_SORT_HAVING_AGGREGATE_FUNCTIONS.build(
+                RuleType.FILL_UP_SORT_HAVING_AGGREGATE.build(
                         logicalSort(logicalHaving(logicalAggregate()))
-                                .when(sort -> sort.getExpressions().stream()
-                                        .anyMatch(e -> 
e.containsType(AggregateFunction.class)))
+                                .when(this::checkSort)
                                 .then(sort -> {
                                     LogicalAggregate<GroupPlan> aggregate = 
sort.child().child();
                                     Resolver resolver = new 
Resolver(aggregate);
@@ -93,7 +112,7 @@ public class FillUpMissingSlots implements 
AnalysisRuleFactory {
                                     });
                                 })
                 ),
-                RuleType.FILL_UP_HAVING_AGGREGATE_FUNCTIONS.build(
+                RuleType.FILL_UP_HAVING_AGGREGATE.build(
                         logicalHaving(logicalAggregate()).then(having -> {
                             LogicalAggregate<GroupPlan> aggregate = 
having.child();
                             Resolver resolver = new Resolver(aggregate);
@@ -104,27 +123,6 @@ public class FillUpMissingSlots implements 
AnalysisRuleFactory {
                                 return new LogicalFilter<>(newPredicates, a);
                             });
                         })
-                ),
-                RuleType.FILL_UP_SORT_PROJECT.build(
-                        logicalSort(logicalProject())
-                                .when(sort -> sort.getExpressions().stream()
-                                        .map(Expression::getInputSlots)
-                                        .flatMap(Set::stream)
-                                        .anyMatch(s -> 
!sort.child().getOutputSet().contains(s)))
-                                .then(sort -> {
-                                    final Builder<NamedExpression> 
projectionsBuilder = ImmutableList.builder();
-                                    
projectionsBuilder.addAll(sort.child().getProjects());
-                                    Set<Slot> notExistedInProject = 
sort.getExpressions().stream()
-                                            .map(Expression::getInputSlots)
-                                            .flatMap(Set::stream)
-                                            .filter(s -> 
!sort.child().getOutputSet().contains(s))
-                                            .collect(Collectors.toSet());
-                                    
projectionsBuilder.addAll(notExistedInProject);
-                                    return new 
LogicalProject(sort.child().getOutput(),
-                                            new 
LogicalSort<>(sort.getOrderKeys(),
-                                                    new 
LogicalProject<>(projectionsBuilder.build(),
-                                                            
sort.child().child())));
-                                })
                 )
         );
     }
@@ -253,4 +251,14 @@ public class FillUpMissingSlots implements 
AnalysisRuleFactory {
         Plan plan = planGenerator.apply(resolver, newAggregate);
         return new LogicalProject<>(projections, plan);
     }
+
+    private boolean checkSort(LogicalSort<? extends LogicalPlan> logicalSort) {
+        return logicalSort.getExpressions().stream()
+                .map(Expression::getInputSlots)
+                .flatMap(Set::stream)
+                .anyMatch(s -> !logicalSort.child().getOutputSet().contains(s))
+                || logicalSort.getOrderKeys().stream()
+                .map(OrderKey::getExpr)
+                .anyMatch(e -> e.containsType(AggregateFunction.class));
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutput.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutput.java
new file mode 100644
index 0000000000..fb04a9c8de
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutput.java
@@ -0,0 +1,99 @@
+// 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.properties.OrderKey;
+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.Expression;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.GroupPlan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+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.LogicalSort;
+import org.apache.doris.nereids.util.ExpressionUtils;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+/**
+ * replace.
+ */
+public class ReplaceExpressionByChildOutput implements AnalysisRuleFactory {
+    @Override
+    public List<Rule> buildRules() {
+        return ImmutableList.<Rule>builder()
+                .add(RuleType.REPLACE_SORT_EXPRESSION_BY_CHILD_OUTPUT.build(
+                        logicalSort(logicalProject()).then(sort -> {
+                            LogicalProject<GroupPlan> project = sort.child();
+                            Map<Expression, Slot> sMap = Maps.newHashMap();
+                            project.getProjects().stream()
+                                    .filter(Alias.class::isInstance)
+                                    .map(Alias.class::cast)
+                                    .forEach(p -> sMap.put(p.child(), 
p.toSlot()));
+                            return replaceSortExpression(sort, sMap);
+                        })
+                ))
+                .add(RuleType.REPLACE_SORT_EXPRESSION_BY_CHILD_OUTPUT.build(
+                        logicalSort(logicalAggregate()).then(sort -> {
+                            LogicalAggregate<GroupPlan> aggregate = 
sort.child();
+                            Map<Expression, Slot> sMap = Maps.newHashMap();
+                            aggregate.getOutputExpressions().stream()
+                                    .filter(Alias.class::isInstance)
+                                    .map(Alias.class::cast)
+                                    .forEach(p -> sMap.put(p.child(), 
p.toSlot()));
+                            return replaceSortExpression(sort, sMap);
+                        })
+                )).add(RuleType.REPLACE_SORT_EXPRESSION_BY_CHILD_OUTPUT.build(
+                        
logicalSort(logicalHaving(logicalAggregate())).then(sort -> {
+                            LogicalAggregate<GroupPlan> aggregate = 
sort.child().child();
+                            Map<Expression, Slot> sMap = Maps.newHashMap();
+                            aggregate.getOutputExpressions().stream()
+                                    .filter(Alias.class::isInstance)
+                                    .map(Alias.class::cast)
+                                    .forEach(p -> sMap.put(p.child(), 
p.toSlot()));
+                            return replaceSortExpression(sort, sMap);
+                        })
+                ))
+                .build();
+    }
+
+    private LogicalPlan replaceSortExpression(LogicalSort<? extends 
LogicalPlan> sort, Map<Expression, Slot> sMap) {
+        List<OrderKey> orderKeys = sort.getOrderKeys();
+        AtomicBoolean changed = new AtomicBoolean(false);
+        List<OrderKey> newKeys = orderKeys.stream().map(k -> {
+            Expression newExpr = ExpressionUtils.replace(k.getExpr(), sMap);
+            if (newExpr != k.getExpr()) {
+                changed.set(true);
+            }
+            return new OrderKey(newExpr, k.isAsc(), k.isNullFirst());
+        }).collect(Collectors.toList());
+        if (changed.get()) {
+            return new LogicalSort<>(newKeys, sort.child());
+        } else {
+            return sort;
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeFunctionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeFunctionTest.java
similarity index 95%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeFunctionTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeFunctionTest.java
index 878d57fe22..c60a63ce78 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeFunctionTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeFunctionTest.java
@@ -15,12 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.util;
+package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.nereids.parser.NereidsParser;
 import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
 import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
 import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
+import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.utframe.TestWithFeService;
 
 import org.junit.jupiter.api.Assertions;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeSubQueryTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeSubQueryTest.java
similarity index 97%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeSubQueryTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeSubQueryTest.java
index 43ca065228..e0a07abc2b 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeSubQueryTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeSubQueryTest.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.util;
+package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.StatementContext;
@@ -23,7 +23,6 @@ import 
org.apache.doris.nereids.glue.translator.PhysicalPlanTranslator;
 import org.apache.doris.nereids.glue.translator.PlanTranslatorContext;
 import org.apache.doris.nereids.parser.NereidsParser;
 import org.apache.doris.nereids.properties.PhysicalProperties;
-import org.apache.doris.nereids.rules.analysis.EliminateAliasNode;
 import org.apache.doris.nereids.trees.expressions.EqualTo;
 import org.apache.doris.nereids.trees.expressions.ExprId;
 import org.apache.doris.nereids.trees.expressions.NamedExpressionUtil;
@@ -31,6 +30,10 @@ import 
org.apache.doris.nereids.trees.expressions.SlotReference;
 import org.apache.doris.nereids.trees.plans.JoinType;
 import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
 import org.apache.doris.nereids.types.BigIntType;
+import org.apache.doris.nereids.util.FieldChecker;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PatternMatchSupported;
+import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.ImmutableList;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeWhereSubqueryTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeWhereSubqueryTest.java
similarity index 99%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeWhereSubqueryTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeWhereSubqueryTest.java
index f3e45631e3..1059d9bd3c 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/AnalyzeWhereSubqueryTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeWhereSubqueryTest.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.util;
+package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.StatementContext;
@@ -44,6 +44,10 @@ import org.apache.doris.nereids.trees.plans.JoinType;
 import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
 import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.VarcharType;
+import org.apache.doris.nereids.util.FieldChecker;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PatternMatchSupported;
+import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.ImmutableList;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/FillUpMissingSlotsTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
similarity index 95%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/parser/FillUpMissingSlotsTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
index c63310e518..642b1d90b4 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/FillUpMissingSlotsTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/FillUpMissingSlotsTest.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.parser;
+package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.common.ExceptionChecker;
 import org.apache.doris.nereids.datasets.tpch.AnalyzeCheckTestBase;
@@ -408,12 +408,11 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Patt
         sumA2 = new Alias(new ExprId(3), new Sum(a2), "SUM(a2)");
         PlanChecker.from(connectContext).analyze(sql)
                 .matchesFromRoot(
-                        logicalProject(
-                                logicalSort(
-                                        logicalAggregate(
-                                                logicalOlapScan()
-                                        
).when(FieldChecker.check("outputExpressions", Lists.newArrayList(a1, sumA2)))
-                                ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA2.toSlot(), true, true))))));
+                        logicalSort(
+                                logicalAggregate(
+                                        logicalOlapScan()
+                                ).when(FieldChecker.check("outputExpressions", 
Lists.newArrayList(a1, sumA2)))
+                        ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA2.toSlot(), true, true)))));
 
         sql = "SELECT a1, SUM(a2) as value FROM t1 GROUP BY a1 ORDER BY 
SUM(a2)";
         a1 = new SlotReference(
@@ -427,12 +426,11 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Patt
         Alias value = new Alias(new ExprId(3), new Sum(a2), "value");
         PlanChecker.from(connectContext).analyze(sql)
                 .matchesFromRoot(
-                        logicalProject(
-                                logicalSort(
-                                        logicalAggregate(
-                                                logicalOlapScan()
-                                        
).when(FieldChecker.check("outputExpressions", Lists.newArrayList(a1, value)))
-                                ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA2.toSlot(), true, true))))));
+                        logicalSort(
+                                logicalAggregate(
+                                        logicalOlapScan()
+                                ).when(FieldChecker.check("outputExpressions", 
Lists.newArrayList(a1, value)))
+                        ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA2.toSlot(), true, true)))));
 
         sql = "SELECT a1, SUM(a2) FROM t1 GROUP BY a1 ORDER BY MIN(pk)";
         a1 = new SlotReference(
@@ -463,12 +461,11 @@ public class FillUpMissingSlotsTest extends 
AnalyzeCheckTestBase implements Patt
         Alias sumA1A2 = new Alias(new ExprId(3), new Sum(new Add(a1, a2)), 
"SUM((a1 + a2))");
         PlanChecker.from(connectContext).analyze(sql)
                 .matchesFromRoot(
-                        logicalProject(
-                                logicalSort(
-                                        logicalAggregate(
-                                                logicalOlapScan()
-                                        
).when(FieldChecker.check("outputExpressions", Lists.newArrayList(a1, sumA1A2)))
-                                ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA1A2.toSlot(), true, true))))));
+                        logicalSort(
+                                logicalAggregate(
+                                        logicalOlapScan()
+                                ).when(FieldChecker.check("outputExpressions", 
Lists.newArrayList(a1, sumA1A2)))
+                        ).when(FieldChecker.check("orderKeys", 
ImmutableList.of(new OrderKey(sumA1A2.toSlot(), true, true)))));
 
         sql = "SELECT a1, SUM(a1 + a2) FROM t1 GROUP BY a1 ORDER BY SUM(a1 + 
a2 + 3)";
         Alias sumA1A23 = new Alias(new ExprId(4), new Sum(new Add(new Add(a1, 
a2), new SmallIntLiteral((short) 3))),
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/RegisterCTETest.java 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/RegisterCTETest.java
similarity index 98%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/util/RegisterCTETest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/RegisterCTETest.java
index 85ac67b453..5ac061ed58 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/RegisterCTETest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/RegisterCTETest.java
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.util;
+package org.apache.doris.nereids.rules.analysis;
 
 import org.apache.doris.nereids.NereidsPlanner;
 import org.apache.doris.nereids.StatementContext;
@@ -29,7 +29,6 @@ import org.apache.doris.nereids.parser.NereidsParser;
 import org.apache.doris.nereids.properties.PhysicalProperties;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleSet;
-import org.apache.doris.nereids.rules.analysis.CTEContext;
 import org.apache.doris.nereids.rules.rewrite.AggregateDisassemble;
 import org.apache.doris.nereids.rules.rewrite.logical.InApplyToJoin;
 import org.apache.doris.nereids.rules.rewrite.logical.PushApplyUnderFilter;
@@ -47,6 +46,10 @@ import 
org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
 import org.apache.doris.nereids.types.BigIntType;
 import org.apache.doris.nereids.types.IntegerType;
 import org.apache.doris.nereids.types.VarcharType;
+import org.apache.doris.nereids.util.FieldChecker;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PatternMatchSupported;
+import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.ImmutableList;
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutputTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutputTest.java
new file mode 100644
index 0000000000..5206dcb402
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/ReplaceExpressionByChildOutputTest.java
@@ -0,0 +1,97 @@
+// 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.properties.OrderKey;
+import org.apache.doris.nereids.trees.expressions.Alias;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.nereids.trees.plans.logical.LogicalHaving;
+import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
+import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
+import org.apache.doris.nereids.types.IntegerType;
+import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.nereids.util.PatternMatchSupported;
+import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.nereids.util.PlanConstructor;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+public class ReplaceExpressionByChildOutputTest implements 
PatternMatchSupported {
+
+    @Test
+    void testSortProject() {
+        SlotReference slotReference = new SlotReference("col1", 
IntegerType.INSTANCE);
+        Alias alias = new Alias(slotReference, "a");
+        LogicalOlapScan logicalOlapScan = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+        LogicalProject<Plan> logicalProject = new 
LogicalProject<>(ImmutableList.of(alias), logicalOlapScan);
+        List<OrderKey> orderKeys = ImmutableList.of(new 
OrderKey(slotReference, true, true));
+        LogicalSort<LogicalProject<Plan>> logicalSort = new 
LogicalSort<>(orderKeys, logicalProject);
+
+        PlanChecker.from(MemoTestUtils.createConnectContext(), logicalSort)
+                .applyBottomUp(new ReplaceExpressionByChildOutput())
+                .matchesFromRoot(
+                        logicalSort(logicalProject()).when(sort ->
+                                ((Slot) 
(sort.getOrderKeys().get(0).getExpr())).getExprId().equals(alias.getExprId()))
+                );
+    }
+
+    @Test
+    void testSortAggregate() {
+        SlotReference slotReference = new SlotReference("col1", 
IntegerType.INSTANCE);
+        Alias alias = new Alias(slotReference, "a");
+        LogicalOlapScan logicalOlapScan = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+        LogicalAggregate<Plan> logicalAggregate = new LogicalAggregate<>(
+                ImmutableList.of(alias), ImmutableList.of(alias), 
logicalOlapScan);
+        List<OrderKey> orderKeys = ImmutableList.of(new 
OrderKey(slotReference, true, true));
+        LogicalSort<LogicalAggregate<Plan>> logicalSort = new 
LogicalSort<>(orderKeys, logicalAggregate);
+
+        PlanChecker.from(MemoTestUtils.createConnectContext(), logicalSort)
+                .applyBottomUp(new ReplaceExpressionByChildOutput())
+                .matchesFromRoot(
+                        logicalSort(logicalAggregate()).when(sort ->
+                                ((Slot) 
(sort.getOrderKeys().get(0).getExpr())).getExprId().equals(alias.getExprId()))
+                );
+    }
+
+    @Test
+    void testSortHavingAggregate() {
+        SlotReference slotReference = new SlotReference("col1", 
IntegerType.INSTANCE);
+        Alias alias = new Alias(slotReference, "a");
+        LogicalOlapScan logicalOlapScan = 
PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+        LogicalAggregate<Plan> logicalAggregate = new LogicalAggregate<>(
+                ImmutableList.of(alias), ImmutableList.of(alias), 
logicalOlapScan);
+        LogicalHaving<Plan> logicalHaving = new 
LogicalHaving<>(BooleanLiteral.TRUE, logicalAggregate);
+        List<OrderKey> orderKeys = ImmutableList.of(new 
OrderKey(slotReference, true, true));
+        LogicalSort<Plan> logicalSort = new LogicalSort<>(orderKeys, 
logicalHaving);
+
+        PlanChecker.from(MemoTestUtils.createConnectContext(), logicalSort)
+                .applyBottomUp(new ReplaceExpressionByChildOutput())
+                .matchesFromRoot(
+                        
logicalSort(logicalHaving(logicalAggregate())).when(sort ->
+                                ((Slot) 
(sort.getOrderKeys().get(0).getExpr())).getExprId().equals(alias.getExprId()))
+                );
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to