This is an automated email from the ASF dual-hosted git repository.

lingmiao 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 f5936aa7ce [enhancement](Nereids): add more implmentation rules. 
(#10335)
f5936aa7ce is described below

commit f5936aa7ce0b0b00fefa599c841cacc018b5e171
Author: jakevin <30525741+jackwe...@users.noreply.github.com>
AuthorDate: Tue Jun 28 17:08:33 2022 +0800

    [enhancement](Nereids): add more implmentation rules. (#10335)
    
    Add more implmentation rules.
    
    Current some `logical` and `physical` operator is different. I change some 
code to make them match.
    
    Implementation
    - Sort:only heap sort
    - Agg
    - OlapScan
---
 .../org/apache/doris/nereids/OperatorVisitor.java  |   4 +-
 .../doris/nereids/operators/AbstractOperator.java  |  16 +-
 .../plans/logical/LogicalAggregation.java          |  74 ++++----
 .../plans/logical/LogicalOlapScan.java}            |  39 ++--
 .../operators/plans/logical/LogicalRelation.java   |   2 +-
 .../operators/plans/logical/LogicalSort.java       |  84 +++------
 .../plans/physical/PhysicalAggregation.java        |  33 ++--
 .../{PhysicalSort.java => PhysicalHeapSort.java}   |  37 ++--
 .../plans/physical/PhysicalUnaryOperator.java      |   4 +
 .../doris/nereids/parser/LogicalPlanBuilder.java   |  86 ++++-----
 .../apache/doris/nereids/properties/OrderKey.java  |   1 +
 .../org/apache/doris/nereids/rules/RuleSet.java    |   4 +-
 .../org/apache/doris/nereids/rules/RuleType.java   |   8 +-
 .../doris/nereids/rules/analysis/BindRelation.java |  11 +-
 ...ction.java => LogicalAggToPhysicalHashAgg.java} |  22 ++-
 .../LogicalFilterToPhysicalFilter.java             |   2 +-
 ...java => LogicalOlapScanToPhysicalOlapScan.java} |  17 +-
 ...n.java => LogicalProjectToPhysicalProject.java} |  14 +-
 ...ter.java => LogicalSortToPhysicalHeapSort.java} |  15 +-
 .../trees/plans/PhysicalPlanTranslator.java        |  29 +--
 .../nereids/trees/plans/PlanOperatorVisitor.java   |   4 +-
 .../java/org/apache/doris/planner/SortNode.java    | 196 ++++++++++-----------
 .../doris/nereids/jobs/RewriteTopDownJobTest.java  |   4 +-
 .../apache/doris/nereids/plan/TestPlanOutput.java  |   5 +-
 ...va => LogicalProjectToPhysicalProjectTest.java} |   4 +-
 25 files changed, 324 insertions(+), 391 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/OperatorVisitor.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/OperatorVisitor.java
index 7b168355ca..d2a7c4ef6e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/OperatorVisitor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/OperatorVisitor.java
@@ -21,9 +21,9 @@ import org.apache.doris.nereids.operators.Operator;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalAggregation;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalHashJoin;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalHeapSort;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
-import org.apache.doris.nereids.operators.plans.physical.PhysicalSort;
 
 /**
  * Base class for the processing of logical and physical operator.
@@ -44,7 +44,7 @@ public abstract class OperatorVisitor<R, C> {
         return null;
     }
 
-    public R visitPhysicalSort(PhysicalSort physicalSort, C context) {
+    public R visitPhysicalHeapSort(PhysicalHeapSort physicalHeapSort, C 
context) {
         return null;
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/AbstractOperator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/AbstractOperator.java
index d3b7a25e92..6dbe1d85c7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/AbstractOperator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/AbstractOperator.java
@@ -28,16 +28,16 @@ import java.util.Objects;
  */
 public abstract class AbstractOperator implements Operator {
     protected final OperatorType type;
-    protected final long limited;
+    protected final long limit;
 
     public AbstractOperator(OperatorType type) {
         this.type = Objects.requireNonNull(type, "type can not be null");
-        this.limited = -1;
+        this.limit = -1;
     }
 
-    public AbstractOperator(OperatorType type, long limited) {
+    public AbstractOperator(OperatorType type, long limit) {
         this.type = type;
-        this.limited = limited;
+        this.limit = limit;
     }
 
     @Override
@@ -45,6 +45,10 @@ public abstract class AbstractOperator implements Operator {
         return type;
     }
 
+    public long getLimit() {
+        return limit;
+    }
+
     /**
      * Child operator should overwrite this method.
      * for example:
@@ -65,8 +69,4 @@ public abstract class AbstractOperator implements Operator {
         return null;
     }
 
-    public long getLimited() {
-        return limited;
-    }
-
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java
index eb6172420a..00088bf1f1 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalAggregation.java
@@ -19,6 +19,7 @@ package org.apache.doris.nereids.operators.plans.logical;
 
 import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.operators.OperatorType;
+import org.apache.doris.nereids.operators.plans.AggPhase;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
 import org.apache.doris.nereids.trees.expressions.Slot;
@@ -31,68 +32,71 @@ import java.util.List;
 
 /**
  * Logical Aggregation plan operator.
- *
- *eg:select a, sum(b), c from table group by a, c;
+ * <p>
+ * eg:select a, sum(b), c from table group by a, c;
  * groupByExpressions: Column field after group by. eg: a, c;
  * outputExpressions: Column field after select. eg: a, sum(b), c;
- *
+ * partitionExprList: Column field after partition by.
+ * <p>
  * Each agg node only contains the select statement field of the same layer,
  * and other agg nodes in the subquery contain.
  */
 public class LogicalAggregation extends LogicalUnaryOperator {
 
-    private final List<Expression> groupByExpressions;
-    private final List<? extends NamedExpression> outputExpressions;
+    private final List<Expression> groupByExprList;
+    private final List<NamedExpression> outputExpressionList;
+    private List<Expression> partitionExprList;
+
+    private AggPhase aggPhase;
 
     /**
      * Desc: Constructor for LogicalAggregation.
      */
-    public LogicalAggregation(List<Expression> groupByExpressions,
-            List<? extends NamedExpression> outputExpressions) {
+    public LogicalAggregation(List<Expression> groupByExprList, 
List<NamedExpression> outputExpressionList) {
         super(OperatorType.LOGICAL_AGGREGATION);
-        this.groupByExpressions = groupByExpressions;
-        this.outputExpressions = outputExpressions;
+        this.groupByExprList = groupByExprList;
+        this.outputExpressionList = outputExpressionList;
     }
 
-    /**
-     * Get GroupByAggregation list.
-     *
-     * @return all group by of this node.
-     */
-    public List<Expression> getGroupByExpressions() {
-        return groupByExpressions;
+    public List<Expression> getPartitionExprList() {
+        return partitionExprList == null ? groupByExprList : partitionExprList;
     }
 
-    /**
-     * Get outputExpressions list.
-     *
-     * @return all agg expressions.
-     */
-    public List<? extends NamedExpression> getoutputExpressions() {
-        return outputExpressions;
+    public void setPartitionExprList(List<Expression> partitionExprList) {
+        this.partitionExprList = partitionExprList;
+    }
+
+    public List<Expression> getGroupByExprList() {
+        return groupByExprList;
+    }
+
+    public List<NamedExpression> getOutputExpressionList() {
+        return outputExpressionList;
+    }
+
+    public AggPhase getAggPhase() {
+        return aggPhase;
     }
 
     @Override
     public String toString() {
-        return "Aggregation (" + "outputExpressions: " + 
StringUtils.join(outputExpressions, ", ")
-                + ", groupByExpressions: " + 
StringUtils.join(groupByExpressions, ", ") + ")";
+        return "Aggregation (" + "outputExpressionList: " + 
StringUtils.join(outputExpressionList, ", ")
+                + ", groupByExprList: " + StringUtils.join(groupByExprList, ", 
") + ")";
     }
 
     @Override
     public List<Slot> computeOutput(Plan input) {
-        return outputExpressions.stream()
-                .map(namedExpr -> {
-                    try {
-                        return namedExpr.toSlot();
-                    } catch (UnboundException e) {
-                        throw new IllegalStateException(e);
-                    }
-                })
-                .collect(ImmutableList.toImmutableList());
+        return outputExpressionList.stream().map(namedExpr -> {
+            try {
+                return namedExpr.toSlot();
+            } catch (UnboundException e) {
+                throw new IllegalStateException(e);
+            }
+        }).collect(ImmutableList.toImmutableList());
     }
 
     @Override
     public List<Expression> getExpressions() {
-        return new 
ImmutableList.Builder<Expression>().addAll(groupByExpressions).addAll(outputExpressions).build();
+        return new 
ImmutableList.Builder<Expression>().addAll(groupByExprList).addAll(outputExpressionList).build();
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOlapScan.java
similarity index 53%
copy from 
fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java
copy to 
fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOlapScan.java
index b01862dff6..b9e61b29ea 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOlapScan.java
@@ -15,41 +15,24 @@
 // specific language governing permissions and limitations
 // under the License.
 
-package org.apache.doris.nereids.properties;
+package org.apache.doris.nereids.operators.plans.logical;
 
-import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.catalog.Table;
+
+import java.util.List;
 
 /**
- * Represents the order key of a statement.
+ * Logical OlapScan operator.
  */
-public class OrderKey {
-
-    private Expression expr;
-
-    private boolean isAsc;
-
-    private boolean nullFirst;
+public class LogicalOlapScan extends LogicalRelation  {
 
     /**
-     * Constructor of OrderKey.
+     * Constructor for LogicalOlapScan.
      *
-     * @param nullFirst True if "NULLS FIRST", false if "NULLS LAST", null if 
not specified.
+     * @param table Doris table
+     * @param qualifier qualified relation name
      */
-    public OrderKey(Expression expr, boolean isAsc, boolean nullFirst) {
-        this.expr = expr;
-        this.isAsc = isAsc;
-        this.nullFirst = nullFirst;
-    }
-
-    public Expression getExpr() {
-        return expr;
-    }
-
-    public boolean isAsc() {
-        return isAsc;
-    }
-
-    public boolean isNullFirst() {
-        return nullFirst;
+    public LogicalOlapScan(Table table, List<String> qualifier) {
+        super(table, qualifier);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalRelation.java
index 0a2563766d..6f7ce83e14 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalRelation.java
@@ -32,7 +32,7 @@ import java.util.Objects;
 /**
  * Logical relation plan operator.
  */
-public class LogicalRelation extends LogicalLeafOperator {
+public abstract class LogicalRelation extends LogicalLeafOperator {
 
     private final Table table;
     private final List<String> qualifier;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java
index b1984051f7..6c63f8a09e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalSort.java
@@ -18,6 +18,7 @@
 package org.apache.doris.nereids.operators.plans.logical;
 
 import org.apache.doris.nereids.operators.OperatorType;
+import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.Slot;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -31,26 +32,24 @@ import java.util.stream.Collectors;
 
 /**
  * Logical Sort plan operator.
- *
+ * <p>
  * eg: select * from table order by a, b desc;
- * sortItems: list of column information after order by. eg:[a, asc],[b, desc].
- * SortItems: Contains order expression information and sorting method. 
Default is ascending.
+ * orderKeys: list of column information after order by. eg:[a, asc],[b, desc].
+ * OrderKey: Contains order expression information and sorting method. Default 
is ascending.
  */
 public class LogicalSort extends LogicalUnaryOperator {
 
-    private List<SortItems> sortItems;
+    // Default offset is 0.
+    private int offset = 0;
+
+    private final List<OrderKey> orderKeys;
 
     /**
-     * Constructor for SortItems.
+     * Constructor for LogicalSort.
      */
-    public LogicalSort(List<SortItems> sortItems) {
+    public LogicalSort(List<OrderKey> orderKeys) {
         super(OperatorType.LOGICAL_SORT);
-        this.sortItems = Objects.requireNonNull(sortItems, "sorItems can not 
be null");
-    }
-
-    @Override
-    public String toString() {
-        return "Sort (" + StringUtils.join(sortItems, ", ") + ")";
+        this.orderKeys = Objects.requireNonNull(orderKeys, "orderKeys can not 
be null");
     }
 
     @Override
@@ -58,57 +57,26 @@ public class LogicalSort extends LogicalUnaryOperator {
         return input.getOutput();
     }
 
-    /**
-     * Get SortItems.
-     *
-     * @return List of SortItems.
-     */
-    public List<SortItems> getSortItems() {
-        return sortItems;
+    public List<OrderKey> getOrderKeys() {
+        return orderKeys;
     }
 
-    @Override
-    public List<Expression> getExpressions() {
-        return new ImmutableList.Builder<Expression>().addAll(
-                sortItems.stream().map(expr -> 
expr.getSort()).collect(Collectors.toList()))
-                .build();
+    public int getOffset() {
+        return offset;
     }
 
-    /**
-     * SortItem. Show sort expressions and their order types.
-     */
-    public static class SortItems {
-        /**
-         * enum of OrderDirection.
-         */
-        public enum OrderDirection {
-            ASC,
-            DESC
-        }
-
-        private final Expression sort;
-        private final OrderDirection orderDirection;
-
-        public SortItems(Expression sort, OrderDirection orderDirection) {
-            this.sort = sort;
-            this.orderDirection = orderDirection;
-        }
-
-        public Expression getSort() {
-            return sort;
-        }
+    public void setOffset(int offset) {
+        this.offset = offset;
+    }
 
-        /**
-         * Get OrderDirection.
-         *
-         * @return boolean.
-         */
-        public OrderDirection getOrderDirection() {
-            return orderDirection;
-        }
+    @Override
+    public String toString() {
+        return "Sort (" + StringUtils.join(orderKeys, ", ") + ")";
+    }
 
-        public String toString() {
-            return "Expression: " + sort.sql() + " OrderDirection: " + 
orderDirection.toString();
-        }
+    @Override
+    public List<Expression> getExpressions() {
+        return new ImmutableList.Builder<Expression>().addAll(
+                
orderKeys.stream().map(OrderKey::getExpr).collect(Collectors.toList())).build();
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalAggregation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalAggregation.java
index 55462751d7..f42072abc2 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalAggregation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalAggregation.java
@@ -20,6 +20,7 @@ package org.apache.doris.nereids.operators.plans.physical;
 import org.apache.doris.nereids.operators.OperatorType;
 import org.apache.doris.nereids.operators.plans.AggPhase;
 import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.PlanOperatorVisitor;
 import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan;
@@ -35,7 +36,7 @@ public class PhysicalAggregation extends 
PhysicalUnaryOperator {
 
     private final List<Expression> groupByExprList;
 
-    private final List<Expression> aggExprList;
+    private final List<NamedExpression> outputExpressionList;
 
     private final List<Expression> partitionExprList;
 
@@ -47,30 +48,30 @@ public class PhysicalAggregation extends 
PhysicalUnaryOperator {
      * Constructor of PhysicalAggNode.
      *
      * @param groupByExprList group by expr list.
-     * @param aggExprList agg expr list.
-     * @param partitionExprList  partition expr list, used for analytic agg.
+     * @param outputExpressionList agg expr list.
+     * @param partitionExprList partition expr list, used for analytic agg.
      * @param usingStream whether it's stream agg.
      */
-    public PhysicalAggregation(List<Expression> groupByExprList, 
List<Expression> aggExprList,
+    public PhysicalAggregation(List<Expression> groupByExprList, 
List<NamedExpression> outputExpressionList,
             List<Expression> partitionExprList, AggPhase aggPhase, boolean 
usingStream) {
         super(OperatorType.PHYSICAL_AGGREGATION);
         this.groupByExprList = groupByExprList;
-        this.aggExprList = aggExprList;
-        this.partitionExprList = partitionExprList;
+        this.outputExpressionList = outputExpressionList;
         this.aggPhase = aggPhase;
+        this.partitionExprList = partitionExprList;
         this.usingStream = usingStream;
     }
 
-    public List<Expression> getGroupByExprList() {
-        return groupByExprList;
+    public AggPhase getAggPhase() {
+        return aggPhase;
     }
 
-    public List<Expression> getAggExprList() {
-        return aggExprList;
+    public List<Expression> getGroupByExprList() {
+        return groupByExprList;
     }
 
-    public AggPhase getAggPhase() {
-        return aggPhase;
+    public List<NamedExpression> getOutputExpressionList() {
+        return outputExpressionList;
     }
 
     public boolean isUsingStream() {
@@ -88,10 +89,8 @@ public class PhysicalAggregation extends 
PhysicalUnaryOperator {
 
     @Override
     public List<Expression> getExpressions() {
-        return new ImmutableList.Builder<Expression>()
-                .addAll(groupByExprList)
-                .addAll(aggExprList)
-                .addAll(partitionExprList)
-                .build();
+        // TODO: partitionExprList maybe null.
+        return new 
ImmutableList.Builder<Expression>().addAll(groupByExprList).addAll(outputExpressionList)
+                .addAll(partitionExprList).build();
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalSort.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalHeapSort.java
similarity index 71%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalSort.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalHeapSort.java
index bf1c831b8f..4637098e55 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalSort.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalHeapSort.java
@@ -32,41 +32,27 @@ import java.util.stream.Collectors;
 /**
  * Physical sort plan operator.
  */
-public class PhysicalSort extends PhysicalUnaryOperator {
-
+public class PhysicalHeapSort extends PhysicalUnaryOperator {
+    // Default offset is 0.
     private final int offset;
 
-    private final int limit;
-
-    private final List<OrderKey> orderList;
-
-    private final boolean useTopN;
+    private final List<OrderKey> orderKeys;
 
     /**
      * Constructor of PhysicalHashJoinNode.
      */
-    public PhysicalSort(int offset, int limit, List<OrderKey> orderList, 
boolean useTopN) {
-        super(OperatorType.PHYSICAL_SORT);
+    public PhysicalHeapSort(List<OrderKey> orderKeys, long limit, int offset) {
+        super(OperatorType.PHYSICAL_SORT, limit);
         this.offset = offset;
-        this.limit = limit;
-        this.orderList = orderList;
-        this.useTopN = useTopN;
+        this.orderKeys = orderKeys;
     }
 
     public int getOffset() {
         return offset;
     }
 
-    public int getLimit() {
-        return limit;
-    }
-
-    public List<OrderKey> getOrderList() {
-        return orderList;
-    }
-
-    public boolean isUseTopN() {
-        return useTopN;
+    public List<OrderKey> getOrderKeys() {
+        return orderKeys;
     }
 
     public boolean hasLimit() {
@@ -75,15 +61,12 @@ public class PhysicalSort extends PhysicalUnaryOperator {
 
     @Override
     public <R, C> R accept(PlanOperatorVisitor<R, C> visitor, Plan plan, C 
context) {
-        return visitor.visitPhysicalSort((PhysicalUnaryPlan<PhysicalSort, 
Plan>) plan, context);
+        return visitor.visitPhysicalSort((PhysicalUnaryPlan<PhysicalHeapSort, 
Plan>) plan, context);
     }
 
     @Override
     public List<Expression> getExpressions() {
         return ImmutableList.<Expression>builder()
-            .addAll(orderList.stream()
-                .map(o -> o.getExpr())
-                .collect(Collectors.toList())
-            ).build();
+                .addAll(orderKeys.stream().map(o -> 
o.getExpr()).collect(Collectors.toList())).build();
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalUnaryOperator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalUnaryOperator.java
index fb2f0812cc..345de2e1ea 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalUnaryOperator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalUnaryOperator.java
@@ -37,6 +37,10 @@ public abstract class PhysicalUnaryOperator extends 
AbstractOperator
         super(type);
     }
 
+    public PhysicalUnaryOperator(OperatorType type, long limit) {
+        super(type, limit);
+    }
+
     @Override
     public PhysicalUnaryPlan toTreeNode(GroupExpression groupExpression) {
         LogicalProperties logicalProperties = 
groupExpression.getParent().getLogicalProperties();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index 6b83a63f73..8cac723572 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -68,8 +68,7 @@ import 
org.apache.doris.nereids.operators.plans.logical.LogicalFilter;
 import org.apache.doris.nereids.operators.plans.logical.LogicalJoin;
 import org.apache.doris.nereids.operators.plans.logical.LogicalProject;
 import org.apache.doris.nereids.operators.plans.logical.LogicalSort;
-import org.apache.doris.nereids.operators.plans.logical.LogicalSort.SortItems;
-import 
org.apache.doris.nereids.operators.plans.logical.LogicalSort.SortItems.OrderDirection;
+import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.trees.analysis.FunctionParams;
 import org.apache.doris.nereids.trees.expressions.Add;
 import org.apache.doris.nereids.trees.expressions.Alias;
@@ -121,9 +120,9 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
     /**
      * Create a logical plan using a where clause.
      */
-    private final BiFunction<WhereClauseContext, LogicalPlan, LogicalPlan> 
withWhereClause =
-            (WhereClauseContext ctx, LogicalPlan plan)
-                    -> new LogicalUnaryPlan(new 
LogicalFilter(expression((ctx.booleanExpression()))), plan);
+    private final BiFunction<WhereClauseContext, LogicalPlan, LogicalPlan> 
withWhereClause
+            = (WhereClauseContext ctx, LogicalPlan plan) -> new 
LogicalUnaryPlan(
+                    new LogicalFilter(expression((ctx.booleanExpression()))), 
plan);
 
     protected <T> T typedVisit(ParseTree ctx) {
         return (T) ctx.accept(this);
@@ -180,8 +179,8 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
     }
 
     private LogicalPlan withQueryOrganization(QueryOrganizationContext ctx, 
LogicalPlan children) {
-        List<SortItems> sortItems = visitQueryOrganization(ctx);
-        return sortItems == null ? children : new LogicalUnaryPlan(new 
LogicalSort(sortItems), children);
+        List<OrderKey> orderKeys = visitQueryOrganization(ctx);
+        return orderKeys == null ? children : new LogicalUnaryPlan(new 
LogicalSort(orderKeys), children);
     }
 
     @Override
@@ -189,12 +188,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         Supplier<LogicalPlan> f = () -> {
             // TODO: support on row relation
             LogicalPlan from = visitFromClause(ctx.fromClause());
-            return withSelectQuerySpecification(
-                    ctx,
-                    ctx.selectClause(),
-                    ctx.whereClause(),
-                    from,
-                    ctx.aggClause());
+            return withSelectQuerySpecification(ctx, ctx.selectClause(), 
ctx.whereClause(), from, ctx.aggClause());
         };
         return ParserUtils.withOrigin(ctx, f);
     }
@@ -232,11 +226,8 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
             AggClauseContext aggClause) {
         Supplier<LogicalPlan> f = () -> {
             //        Filter(expression(ctx.booleanExpression), plan);
-            LogicalPlan plan = visitCommonSelectQueryClausePlan(
-                    relation,
-                    visitNamedExpressionSeq(selectClause.namedExpressionSeq()),
-                    whereClause,
-                    aggClause);
+            LogicalPlan plan = visitCommonSelectQueryClausePlan(relation,
+                    
visitNamedExpressionSeq(selectClause.namedExpressionSeq()), whereClause, 
aggClause);
             // TODO: process hint
             return plan;
         };
@@ -287,8 +278,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
             if (left == null) {
                 left = right;
             } else {
-                left = new LogicalBinaryPlan(
-                        new LogicalJoin(JoinType.INNER_JOIN, 
Optional.empty()), left, right);
+                left = new LogicalBinaryPlan(new 
LogicalJoin(JoinType.INNER_JOIN, Optional.empty()), left, right);
             }
             left = withJoinRelations(left, relation);
         }
@@ -328,16 +318,14 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
                 condition = expression(joinCriteria.booleanExpression());
             }
 
-            last = new LogicalBinaryPlan(
-                    new LogicalJoin(joinType, Optional.ofNullable(condition)),
-                    last, plan(join.relationPrimary())
-            );
+            last = new LogicalBinaryPlan(new LogicalJoin(joinType, 
Optional.ofNullable(condition)), last,
+                    plan(join.relationPrimary()));
         }
         return last;
     }
 
-    private LogicalPlan withAggClause(List<NamedExpression> aggExpressions,
-            GroupByItemContext ctx, LogicalPlan aggClause) {
+    private LogicalPlan withAggClause(List<NamedExpression> aggExpressions, 
GroupByItemContext ctx,
+            LogicalPlan aggClause) {
         List<Expression> tmpExpressions = new ArrayList<>();
         for (ExpressionContext expressionCtx : ctx.expression()) {
             tmpExpressions.add(typedVisit(expressionCtx));
@@ -346,35 +334,32 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
     }
 
     /**
-     * Generate sortItems.
+     * Generate OrderKey.
      *
      * @param ctx SortItemContext
-     * @return SortItems
+     * @return OrderKey
      */
-    public SortItems genSortItems(SortItemContext ctx) {
-        OrderDirection orderDirection;
-        if (ctx.DESC() != null) {
-            orderDirection = OrderDirection.DESC;
-        } else {
-            orderDirection = OrderDirection.ASC;
-        }
+    public OrderKey genOrderKeys(SortItemContext ctx) {
+        boolean isAsc = ctx.DESC() == null;
+        // TODO(wj): isNullFirst
+        boolean isNullFirst = true;
         Expression expression = typedVisit(ctx.expression());
-        return new SortItems(expression, orderDirection);
+        return new OrderKey(expression, isAsc, isNullFirst);
     }
 
     /**
-     * Create SortItems list.
+     * Create OrderKey list.
      *
      * @param ctx QueryOrganizationContext
-     * @return List of SortItems
+     * @return List of OrderKey
      */
-    public List<SortItems> visitQueryOrganization(QueryOrganizationContext 
ctx) {
-        List<SortItems> sortItems = new ArrayList<>();
+    public List<OrderKey> visitQueryOrganization(QueryOrganizationContext ctx) 
{
+        List<OrderKey> orderKeys = new ArrayList<>();
         if (ctx.sortClause().ORDER() != null) {
             for (SortItemContext sortItemContext : 
ctx.sortClause().sortItem()) {
-                sortItems.add(genSortItems(sortItemContext));
+                orderKeys.add(genOrderKeys(sortItemContext));
             }
-            return new ArrayList<>(sortItems);
+            return new ArrayList<>(orderKeys);
         } else {
             return null;
         }
@@ -438,8 +423,8 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
             final QualifiedNameContext qualifiedNameContext = 
ctx.qualifiedName();
             List<String> target;
             if (qualifiedNameContext != null) {
-                target = qualifiedNameContext.identifier().stream()
-                        
.map(RuleContext::getText).collect(Collectors.toList());
+                target = 
qualifiedNameContext.identifier().stream().map(RuleContext::getText)
+                        .collect(Collectors.toList());
             } else {
                 target = Lists.newArrayList();
             }
@@ -530,7 +515,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
      * Create a predicated expression. A predicated expression is a normal 
expression with a
      * predicate attached to it, for example:
      * {{{
-     *    a + 1 IS NULL
+     * a + 1 IS NULL
      * }}}
      */
     @Override
@@ -568,11 +553,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
      */
     public Expression withBetween(PredicateContext ctx, Expression e) {
         boolean isNotBetween = ctx.NOT() != null ? true : false;
-        BetweenPredicate betweenPredicate = new BetweenPredicate(
-                e,
-                expression(ctx.lower),
-                expression(ctx.upper)
-        );
+        BetweenPredicate betweenPredicate = new BetweenPredicate(e, 
expression(ctx.lower), expression(ctx.upper));
         return isNotBetween ? new Not(betweenPredicate) : betweenPredicate;
     }
 
@@ -597,7 +578,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         return genArithmetic(ctx.operator, left, right);
     }
 
-    private Arithmetic  genArithmetic(Token token, Expression left, Expression 
right) {
+    private Arithmetic genArithmetic(Token token, Expression left, Expression 
right) {
         switch (token.getType()) {
             case DorisParser.ASTERISK:
                 return new Multiply(left, right);
@@ -626,8 +607,7 @@ public class LogicalPlanBuilder extends 
DorisParserBaseVisitor<Object> {
         }
 
         return new FunctionCall(functionName,
-                new FunctionParams(ctx.aggFunction().DISTINCT() != null,
-                        expression(ctx.aggFunction().expression())));
+                new FunctionParams(ctx.aggFunction().DISTINCT() != null, 
expression(ctx.aggFunction().expression())));
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java
index b01862dff6..9cbf800d6e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/OrderKey.java
@@ -26,6 +26,7 @@ public class OrderKey {
 
     private Expression expr;
 
+    // Order is ascending.
     private boolean isAsc;
 
     private boolean nullFirst;
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 657ab82c76..fda9440e36 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
@@ -22,7 +22,7 @@ import 
org.apache.doris.nereids.rules.exploration.join.JoinCommutative;
 import org.apache.doris.nereids.rules.exploration.join.JoinLeftAssociative;
 import 
org.apache.doris.nereids.rules.implementation.LogicalFilterToPhysicalFilter;
 import org.apache.doris.nereids.rules.implementation.LogicalJoinToHashJoin;
-import 
org.apache.doris.nereids.rules.implementation.LogicalProjectionToPhysicalProjection;
+import 
org.apache.doris.nereids.rules.implementation.LogicalProjectToPhysicalProject;
 import org.apache.doris.nereids.trees.TreeNode;
 import org.apache.doris.nereids.trees.plans.Plan;
 
@@ -46,7 +46,7 @@ public class RuleSet {
 
     public static final List<Rule<Plan>> IMPLEMENTATION_RULES = 
planRuleFactories()
             .add(new LogicalJoinToHashJoin())
-            .add(new LogicalProjectionToPhysicalProjection())
+            .add(new LogicalProjectToPhysicalProject())
             .add(new LogicalFilterToPhysicalFilter())
             .build();
 
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 93f9e846df..a2caa236c2 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
@@ -42,12 +42,12 @@ public enum RuleType {
     LOGICAL_JOIN_EXCHANGE(RuleTypeClass.EXPLORATION),
 
     // implementation rules
+    LOGICAL_AGG_TO_PHYSICAL_HASH_AGG_RULE(RuleTypeClass.IMPLEMENTATION),
     LOGICAL_JOIN_TO_HASH_JOIN_RULE(RuleTypeClass.IMPLEMENTATION),
-    
LOGICAL_PROJECTION_TO_PHYSICAL_PROJECTION_RULE(RuleTypeClass.IMPLEMENTATION),
+    LOGICAL_PROJECT_TO_PHYSICAL_PROJECT_RULE(RuleTypeClass.IMPLEMENTATION),
     LOGICAL_FILTER_TO_PHYSICAL_FILTER_RULE(RuleTypeClass.IMPLEMENTATION),
-    LOGICAL_LIMIT_TO_PHYSICAL_LIMIT_RULE(RuleTypeClass.IMPLEMENTATION),
-    LOGICAL_JOIN_TO_HASH_AGG_RULE(RuleTypeClass.IMPLEMENTATION),
-    LOGICAL_JOIN_TO_OLAP_SCAN_RULE(RuleTypeClass.IMPLEMENTATION),
+    LOGICAL_SORT_TO_PHYSICAL_HEAP_SORT_RULE(RuleTypeClass.IMPLEMENTATION),
+    LOGICAL_OLAP_SCAN_TO_PHYSICAL_OLAP_SCAN_RULE(RuleTypeClass.IMPLEMENTATION),
     IMPLEMENTATION_SENTINEL(RuleTypeClass.IMPLEMENTATION),
 
     // sentinel, use to count rules
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
index 88a4b38f02..d51791ca86 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java
@@ -20,7 +20,7 @@ package org.apache.doris.nereids.rules.analysis;
 import org.apache.doris.catalog.Catalog;
 import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.Table;
-import org.apache.doris.nereids.operators.plans.logical.LogicalRelation;
+import org.apache.doris.nereids.operators.plans.logical.LogicalOlapScan;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
@@ -45,13 +45,14 @@ public class BindRelation extends OneAnalysisRuleFactory {
                 case 1: {
                     List<String> qualifier = 
Lists.newArrayList(connectContext.getDatabase(), nameParts.get(0));
                     Table table = getTable(qualifier, 
connectContext.getCatalog());
-                    LogicalRelation relation = new LogicalRelation(table, 
qualifier);
-                    return new LogicalLeafPlan<>(relation);
+                    // TODO: should generate different Scan sub class 
according to table's type
+                    LogicalOlapScan olapScan = new LogicalOlapScan(table, 
qualifier);
+                    return new LogicalLeafPlan<>(olapScan);
                 }
                 case 2: {
                     Table table = getTable(nameParts, 
connectContext.getCatalog());
-                    LogicalRelation relation = new LogicalRelation(table, 
nameParts);
-                    return new LogicalLeafPlan<>(relation);
+                    LogicalOlapScan olapScan = new LogicalOlapScan(table, 
nameParts);
+                    return new LogicalLeafPlan<>(olapScan);
                 }
                 default:
                     throw new IllegalStateException("Table name ["
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalAggToPhysicalHashAgg.java
similarity index 60%
copy from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
copy to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalAggToPhysicalHashAgg.java
index 66a2b8ad73..5ea7138473 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalAggToPhysicalHashAgg.java
@@ -17,21 +17,27 @@
 
 package org.apache.doris.nereids.rules.implementation;
 
-import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalAggregation;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
 
 /**
- * Implementation rule that convert logical join to physical hash join.
+ * Implementation rule that convert logical aggregation to physical hash 
aggregation.
  */
-public class LogicalProjectionToPhysicalProjection extends 
OneImplementationRuleFactory {
+public class LogicalAggToPhysicalHashAgg extends OneImplementationRuleFactory {
     @Override
     public Rule<Plan> build() {
-        return logicalProject().then(projection -> plan(
-                new PhysicalProject(projection.getOperator().getProjects()),
-                projection.getLogicalProperties(),
-                projection.child()
-        )).toRule(RuleType.LOGICAL_PROJECTION_TO_PHYSICAL_PROJECTION_RULE);
+        return logicalAggregation().then(agg -> plan(
+            new PhysicalAggregation(
+                // TODO: for use a function to judge whether use stream
+                agg.getOperator().getGroupByExprList(),
+                agg.getOperator().getOutputExpressionList(),
+                agg.getOperator().getPartitionExprList(),
+                agg.getOperator().getAggPhase(),
+                false),
+            agg.getLogicalProperties(),
+            agg.child()
+        )).toRule(RuleType.LOGICAL_AGG_TO_PHYSICAL_HASH_AGG_RULE);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
index db6e95cc98..1d6afa2f08 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
@@ -23,7 +23,7 @@ import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
 
 /**
- * Implementation rule that convert logical join to physical hash join.
+ * Implementation rule that convert logical filter to physical filter.
  */
 public class LogicalFilterToPhysicalFilter extends 
OneImplementationRuleFactory {
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
similarity index 64%
copy from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
copy to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
index 66a2b8ad73..dc9e8fff7a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalOlapScanToPhysicalOlapScan.java
@@ -17,21 +17,22 @@
 
 package org.apache.doris.nereids.rules.implementation;
 
-import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
 
 /**
- * Implementation rule that convert logical join to physical hash join.
+ * Implementation rule that convert logical OlapScan to physical OlapScan.
  */
-public class LogicalProjectionToPhysicalProjection extends 
OneImplementationRuleFactory {
+public class LogicalOlapScanToPhysicalOlapScan extends 
OneImplementationRuleFactory {
     @Override
     public Rule<Plan> build() {
-        return logicalProject().then(projection -> plan(
-                new PhysicalProject(projection.getOperator().getProjects()),
-                projection.getLogicalProperties(),
-                projection.child()
-        )).toRule(RuleType.LOGICAL_PROJECTION_TO_PHYSICAL_PROJECTION_RULE);
+        return logicalOlapScan().then(olapScan -> plan(
+                        // TODO: olapScan should get (OlapTable);
+                        new PhysicalOlapScan((OlapTable) 
olapScan.getOperator().getTable(),
+                                olapScan.getOperator().getQualifier()), 
olapScan.getLogicalProperties()))
+                .toRule(RuleType.LOGICAL_OLAP_SCAN_TO_PHYSICAL_OLAP_SCAN_RULE);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProject.java
similarity index 71%
rename from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
rename to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProject.java
index 66a2b8ad73..67b665195e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjection.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProject.java
@@ -23,15 +23,15 @@ import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
 
 /**
- * Implementation rule that convert logical join to physical hash join.
+ * Implementation rule that convert logical project to physical project.
  */
-public class LogicalProjectionToPhysicalProjection extends 
OneImplementationRuleFactory {
+public class LogicalProjectToPhysicalProject extends 
OneImplementationRuleFactory {
     @Override
     public Rule<Plan> build() {
-        return logicalProject().then(projection -> plan(
-                new PhysicalProject(projection.getOperator().getProjects()),
-                projection.getLogicalProperties(),
-                projection.child()
-        )).toRule(RuleType.LOGICAL_PROJECTION_TO_PHYSICAL_PROJECTION_RULE);
+        return logicalProject().then(project -> plan(
+                new PhysicalProject(project.getOperator().getProjects()),
+                project.getLogicalProperties(),
+                project.child()
+        )).toRule(RuleType.LOGICAL_PROJECT_TO_PHYSICAL_PROJECT_RULE);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalSortToPhysicalHeapSort.java
similarity index 70%
copy from 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
copy to 
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalSortToPhysicalHeapSort.java
index db6e95cc98..e15ab360f4 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalFilterToPhysicalFilter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/LogicalSortToPhysicalHeapSort.java
@@ -17,21 +17,20 @@
 
 package org.apache.doris.nereids.rules.implementation;
 
-import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalHeapSort;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.plans.Plan;
 
 /**
- * Implementation rule that convert logical join to physical hash join.
+ * Implementation rule that convert logical sort to physical sort.
  */
-public class LogicalFilterToPhysicalFilter extends 
OneImplementationRuleFactory {
+public class LogicalSortToPhysicalHeapSort extends 
OneImplementationRuleFactory {
     @Override
     public Rule<Plan> build() {
-        return logicalFilter().then(filter -> plan(
-            new PhysicalFilter(filter.getOperator().getPredicates()),
-            filter.getLogicalProperties(),
-            filter.child()
-        )).toRule(RuleType.LOGICAL_FILTER_TO_PHYSICAL_FILTER_RULE);
+        return logicalSort().then(sort -> plan(
+                        new 
PhysicalHeapSort(sort.getOperator().getOrderKeys(), 
sort.getOperator().getLimit(),
+                                sort.getOperator().getOffset()), 
sort.getLogicalProperties(), sort.child()))
+                .toRule(RuleType.LOGICAL_SORT_TO_PHYSICAL_HEAP_SORT_RULE);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java
index 016b206915..23859d43b5 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java
@@ -30,13 +30,14 @@ import org.apache.doris.nereids.operators.plans.JoinType;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalAggregation;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalHashJoin;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalHeapSort;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalOperator;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
-import org.apache.doris.nereids.operators.plans.physical.PhysicalSort;
 import org.apache.doris.nereids.properties.OrderKey;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.ExpressionConverter;
+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.plans.physical.PhysicalBinaryPlan;
@@ -95,9 +96,9 @@ public class PhysicalPlanTranslator extends 
PlanOperatorVisitor<PlanFragment, Pl
         ArrayList<Expr> execGroupingExpressions = 
groupByExpressionList.stream()
                 .map(e -> ExpressionConverter.convert(e, 
context)).collect(Collectors.toCollection(ArrayList::new));
 
-        List<Expression> aggExpressionList = 
physicalAggregation.getAggExprList();
+        List<NamedExpression> outputExpressionList = 
physicalAggregation.getOutputExpressionList();
         // TODO: agg function could be other expr type either
-        ArrayList<FunctionCallExpr> execAggExpressions = 
aggExpressionList.stream()
+        ArrayList<FunctionCallExpr> execAggExpressions = 
outputExpressionList.stream()
                 .map(e -> (FunctionCallExpr) ExpressionConverter.convert(e, 
context))
                 .collect(Collectors.toCollection(ArrayList::new));
 
@@ -147,20 +148,21 @@ public class PhysicalPlanTranslator extends 
PlanOperatorVisitor<PlanFragment, Pl
     }
 
     @Override
-    public PlanFragment visitPhysicalSort(PhysicalUnaryPlan<PhysicalSort, 
Plan> sort,
+    public PlanFragment visitPhysicalSort(PhysicalUnaryPlan<PhysicalHeapSort, 
Plan> sort,
             PlanTranslatorContext context) {
         PlanFragment childFragment = visit(sort.child(0), context);
-        PhysicalSort physicalSort = sort.getOperator();
+        // TODO: Why doesn't the sort node translate if the childfragment is a 
single instance?
+        PhysicalHeapSort physicalHeapSort = sort.getOperator();
         if (!childFragment.isPartitioned()) {
             return childFragment;
         }
-        long limit = physicalSort.getLimit();
+        long limit = physicalHeapSort.getLimit();
 
         List<Expr> execOrderingExprList = Lists.newArrayList();
         List<Boolean> ascOrderList = Lists.newArrayList();
         List<Boolean> nullsFirstParamList = Lists.newArrayList();
 
-        List<OrderKey> orderKeyList = physicalSort.getOrderList();
+        List<OrderKey> orderKeyList = physicalHeapSort.getOrderKeys();
         orderKeyList.forEach(k -> {
             execOrderingExprList.add(ExpressionConverter.convert(k.getExpr(), 
context));
             ascOrderList.add(k.isAsc());
@@ -172,16 +174,17 @@ public class PhysicalPlanTranslator extends 
PlanOperatorVisitor<PlanFragment, Pl
         SortInfo sortInfo = new SortInfo(execOrderingExprList, ascOrderList, 
nullsFirstParamList, tupleDesc);
 
         PlanNode childNode = childFragment.getPlanRoot();
-        SortNode sortNode = new SortNode(context.nextNodeId(), childNode, 
sortInfo, physicalSort.isUseTopN(),
-                physicalSort.hasLimit(), physicalSort.getOffset());
+        // TODO: notice topN
+        SortNode sortNode = new SortNode(context.nextNodeId(), childNode, 
sortInfo, true,
+                physicalHeapSort.hasLimit(), physicalHeapSort.getOffset());
 
         PlanFragment mergeFragment = createParentFragment(childFragment, 
DataPartition.UNPARTITIONED, context);
         ExchangeNode exchNode = (ExchangeNode) mergeFragment.getPlanRoot();
         exchNode.unsetLimit();
-        if (physicalSort.hasLimit()) {
+        if (physicalHeapSort.hasLimit()) {
             exchNode.setLimit(limit);
         }
-        long offset = physicalSort.getOffset();
+        long offset = physicalHeapSort.getOffset();
         exchNode.setMergeInfo(sortNode.getSortInfo(), offset);
 
         // Child nodes should not process the offset. If there is a limit,
@@ -216,7 +219,7 @@ public class PhysicalPlanTranslator extends 
PlanOperatorVisitor<PlanFragment, Pl
                 || physicalHashJoin.getJoinType().equals(JoinType.INNER_JOIN) 
&& eqExprList.isEmpty()) {
             CrossJoinNode crossJoinNode = new 
CrossJoinNode(context.nextNodeId(), leftFragment.getPlanRoot(),
                     rightFragment.getPlanRoot(), null);
-            crossJoinNode.setLimit(physicalHashJoin.getLimited());
+            crossJoinNode.setLimit(physicalHashJoin.getLimit());
             List<Expr> conjuncts = 
Utils.extractConjuncts(predicateExpr).stream()
                     .map(e -> ExpressionConverter.convert(e, context))
                     .collect(Collectors.toCollection(ArrayList::new));
@@ -249,7 +252,7 @@ public class PhysicalPlanTranslator extends 
PlanOperatorVisitor<PlanFragment, Pl
         hashJoinNode.setChild(0, leftFragmentPlanRoot);
         hashJoinNode.setChild(1, leftFragmentPlanRoot);
         
hashJoinNode.setDistributionMode(HashJoinNode.DistributionMode.PARTITIONED);
-        hashJoinNode.setLimit(physicalHashJoin.getLimited());
+        hashJoinNode.setLimit(physicalHashJoin.getLimit());
         leftFragment.setDestination((ExchangeNode) 
rightFragment.getPlanRoot());
         rightFragment.setDestination((ExchangeNode) leftFragmentPlanRoot);
         PlanFragment result = new PlanFragment(context.nextFragmentId(), 
hashJoinNode, leftFragment.getDataPartition());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanOperatorVisitor.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanOperatorVisitor.java
index 52f17f8bce..61a398c219 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanOperatorVisitor.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanOperatorVisitor.java
@@ -23,9 +23,9 @@ import 
org.apache.doris.nereids.operators.plans.logical.LogicalRelation;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalAggregation;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalFilter;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalHashJoin;
+import org.apache.doris.nereids.operators.plans.physical.PhysicalHeapSort;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalOlapScan;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalProject;
-import org.apache.doris.nereids.operators.plans.physical.PhysicalSort;
 import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan;
@@ -75,7 +75,7 @@ public abstract class PlanOperatorVisitor<R, C> {
         return visit(olapScan, context);
     }
 
-    public R visitPhysicalSort(PhysicalUnaryPlan<PhysicalSort, Plan> sort, C 
context) {
+    public R visitPhysicalSort(PhysicalUnaryPlan<PhysicalHeapSort, Plan> sort, 
C context) {
         return visit(sort, context);
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java
index 2a7d3e7b29..134891a1b6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java
@@ -54,35 +54,19 @@ import java.util.Set;
  */
 public class SortNode extends PlanNode {
     private static final Logger LOG = LogManager.getLogger(SortNode.class);
+    // info_.sortTupleSlotExprs_ substituted with the outputSmap_ for 
materialized slots in init().
+    List<Expr> resolvedTupleExprs;
     private final SortInfo info;
     private final boolean  useTopN;
     private final boolean  isDefaultLimit;
-
     private long offset;
     // if true, the output of this node feeds an AnalyticNode
     private boolean isAnalyticSort;
-
-    // info_.sortTupleSlotExprs_ substituted with the outputSmap_ for 
materialized slots in init().
-    List<Expr> resolvedTupleExprs;
-
-    public void setIsAnalyticSort(boolean v) {
-        isAnalyticSort = v;
-    }
-
-    public boolean isAnalyticSort() {
-        return isAnalyticSort;
-    }
-
     private DataPartition inputPartition;
 
-    public void setInputPartition(DataPartition inputPartition) {
-        this.inputPartition = inputPartition;
-    }
-
-    public DataPartition getInputPartition() {
-        return inputPartition;
-    }
-
+    /**
+     * Constructor.
+     */
     public SortNode(PlanNodeId id, PlanNode input, SortInfo info, boolean 
useTopN,
                     boolean isDefaultLimit, long offset) {
         super(id, useTopN ? "TOP-N" : "SORT", StatisticalType.SORT_NODE);
@@ -98,7 +82,7 @@ public class SortNode extends PlanNode {
     }
 
     /**
-     * Clone 'inputSortNode' for distributed Top-N
+     * Clone 'inputSortNode' for distributed Top-N.
      */
     public SortNode(PlanNodeId id, SortNode inputSortNode, PlanNode child) {
         super(id, inputSortNode, inputSortNode.useTopN ? "TOP-N" : "SORT", 
StatisticalType.SORT_NODE);
@@ -109,6 +93,22 @@ public class SortNode extends PlanNode {
         this.offset = inputSortNode.offset;
     }
 
+    public void setIsAnalyticSort(boolean v) {
+        isAnalyticSort = v;
+    }
+
+    public boolean isAnalyticSort() {
+        return isAnalyticSort;
+    }
+
+    public DataPartition getInputPartition() {
+        return inputPartition;
+    }
+
+    public void setInputPartition(DataPartition inputPartition) {
+        this.inputPartition = inputPartition;
+    }
+
     public long getOffset() {
         return offset;
     }
@@ -122,14 +122,33 @@ public class SortNode extends PlanNode {
     }
 
     @Override
-    public void getMaterializedIds(Analyzer analyzer, List<SlotId> ids) {
-        super.getMaterializedIds(analyzer, ids);
-        Expr.getIds(info.getOrderingExprs(), null, ids);
+    public void setCompactData(boolean on) {
+        this.compactData = on;
     }
 
     @Override
-    public void setCompactData(boolean on) {
-        this.compactData = on;
+    public String getNodeExplainString(String detailPrefix, TExplainLevel 
detailLevel) {
+        if (detailLevel == TExplainLevel.BRIEF) {
+            return "";
+        }
+
+        StringBuilder output = new StringBuilder();
+        output.append(detailPrefix + "order by: ");
+        Iterator<Expr> expr = info.getOrderingExprs().iterator();
+        Iterator<Boolean> isAsc = info.getIsAscOrder().iterator();
+        boolean start = true;
+        while (expr.hasNext()) {
+            if (start) {
+                start = false;
+            } else {
+                output.append(", ");
+            }
+            output.append(expr.next().toSql() + " ");
+            output.append(isAsc.next() ? "ASC" : "DESC");
+        }
+        output.append("\n");
+        output.append(detailPrefix + "offset: " + offset + "\n");
+        return output.toString();
     }
 
     @Override
@@ -160,77 +179,6 @@ public class SortNode extends PlanNode {
         LOG.debug("stats Sort: cardinality=" + Long.toString(cardinality));
     }
 
-    @Override
-    public Set<SlotId> computeInputSlotIds() throws NotImplementedException {
-        List<SlotId> result = Lists.newArrayList();
-        Expr.getIds(resolvedTupleExprs, null, result);
-        return new HashSet<>(result);
-    }
-
-    @Override
-    protected String debugString() {
-        List<String> strings = Lists.newArrayList();
-        for (Boolean isAsc : info.getIsAscOrder()) {
-            strings.add(isAsc ? "a" : "d");
-        }
-        return MoreObjects.toStringHelper(this).add("ordering_exprs",
-                Expr.debugString(info.getOrderingExprs())).add("is_asc",
-                "[" + Joiner.on(" ").join(strings) + 
"]").addValue(super.debugString()).toString();
-    }
-
-    @Override
-    protected void toThrift(TPlanNode msg) {
-        msg.node_type = TPlanNodeType.SORT_NODE;
-        TSortInfo sortInfo = new TSortInfo(
-                Expr.treesToThrift(info.getOrderingExprs()),
-                info.getIsAscOrder(),
-                info.getNullsFirst());
-        Preconditions.checkState(tupleIds.size() == 1, "Incorrect size for 
tupleIds in SortNode");
-        sortInfo.setSortTupleSlotExprs(Expr.treesToThrift(resolvedTupleExprs));
-        TSortNode sortNode = new TSortNode(sortInfo, useTopN);
-
-        msg.sort_node = sortNode;
-        msg.sort_node.setOffset(offset);
-
-        // TODO(lingbin): remove blew codes, because it is duplicate with 
TSortInfo
-        
msg.sort_node.setOrderingExprs(Expr.treesToThrift(info.getOrderingExprs()));
-        msg.sort_node.setIsAscOrder(info.getIsAscOrder());
-        msg.sort_node.setNullsFirst(info.getNullsFirst());
-        if (info.getSortTupleSlotExprs() != null) {
-            
msg.sort_node.setSortTupleSlotExprs(Expr.treesToThrift(info.getSortTupleSlotExprs()));
-        }
-    }
-
-    @Override
-    public String getNodeExplainString(String detailPrefix, TExplainLevel 
detailLevel) {
-        if (detailLevel == TExplainLevel.BRIEF) {
-            return "";
-        }
-
-        StringBuilder output = new StringBuilder();
-        output.append(detailPrefix + "order by: ");
-        Iterator<Expr> expr = info.getOrderingExprs().iterator();
-        Iterator<Boolean> isAsc = info.getIsAscOrder().iterator();
-        boolean start = true;
-        while (expr.hasNext()) {
-            if (start) {
-                start = false;
-            } else {
-                output.append(", ");
-            }
-            output.append(expr.next().toSql() + " ");
-            output.append(isAsc.next() ? "ASC" : "DESC");
-        }
-        output.append("\n");
-        output.append(detailPrefix + "offset: " + offset + "\n");
-        return output.toString();
-    }
-
-    @Override
-    public int getNumInstances() {
-        return children.get(0).getNumInstances();
-    }
-
     public void init(Analyzer analyzer) throws UserException {
         // Compute the memory layout for the generated tuple.
         computeStats(analyzer);
@@ -272,4 +220,56 @@ public class SortNode extends PlanNode {
             LOG.debug("sort input exprs: " + 
Expr.debugString(resolvedTupleExprs));
         }
     }
+
+    @Override
+    public void getMaterializedIds(Analyzer analyzer, List<SlotId> ids) {
+        super.getMaterializedIds(analyzer, ids);
+        Expr.getIds(info.getOrderingExprs(), null, ids);
+    }
+
+    @Override
+    protected void toThrift(TPlanNode msg) {
+        msg.node_type = TPlanNodeType.SORT_NODE;
+        TSortInfo sortInfo = new TSortInfo(
+                Expr.treesToThrift(info.getOrderingExprs()),
+                info.getIsAscOrder(),
+                info.getNullsFirst());
+        Preconditions.checkState(tupleIds.size() == 1, "Incorrect size for 
tupleIds in SortNode");
+        sortInfo.setSortTupleSlotExprs(Expr.treesToThrift(resolvedTupleExprs));
+        TSortNode sortNode = new TSortNode(sortInfo, useTopN);
+
+        msg.sort_node = sortNode;
+        msg.sort_node.setOffset(offset);
+
+        // TODO(lingbin): remove blew codes, because it is duplicate with 
TSortInfo
+        
msg.sort_node.setOrderingExprs(Expr.treesToThrift(info.getOrderingExprs()));
+        msg.sort_node.setIsAscOrder(info.getIsAscOrder());
+        msg.sort_node.setNullsFirst(info.getNullsFirst());
+        if (info.getSortTupleSlotExprs() != null) {
+            
msg.sort_node.setSortTupleSlotExprs(Expr.treesToThrift(info.getSortTupleSlotExprs()));
+        }
+    }
+
+    @Override
+    protected String debugString() {
+        List<String> strings = Lists.newArrayList();
+        for (Boolean isAsc : info.getIsAscOrder()) {
+            strings.add(isAsc ? "a" : "d");
+        }
+        return MoreObjects.toStringHelper(this).add("ordering_exprs",
+                Expr.debugString(info.getOrderingExprs())).add("is_asc",
+                "[" + Joiner.on(" ").join(strings) + 
"]").addValue(super.debugString()).toString();
+    }
+
+    @Override
+    public int getNumInstances() {
+        return children.get(0).getNumInstances();
+    }
+
+    @Override
+    public Set<SlotId> computeInputSlotIds() throws NotImplementedException {
+        List<SlotId> result = Lists.newArrayList();
+        Expr.getIds(resolvedTupleExprs, null, result);
+        return new HashSet<>(result);
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/RewriteTopDownJobTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/RewriteTopDownJobTest.java
index 152d827fc7..4c620c8764 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/RewriteTopDownJobTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/RewriteTopDownJobTest.java
@@ -28,8 +28,8 @@ import org.apache.doris.nereids.memo.Group;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.memo.Memo;
 import org.apache.doris.nereids.operators.OperatorType;
+import org.apache.doris.nereids.operators.plans.logical.LogicalOlapScan;
 import org.apache.doris.nereids.operators.plans.logical.LogicalProject;
-import org.apache.doris.nereids.operators.plans.logical.LogicalRelation;
 import org.apache.doris.nereids.properties.PhysicalProperties;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
@@ -53,7 +53,7 @@ public class RewriteTopDownJobTest implements Plans {
         @Override
         public Rule<Plan> build() {
             return unboundRelation().then(unboundRelation -> plan(
-                new LogicalRelation(new Table(0, "test", Table.TableType.OLAP, 
ImmutableList.of(
+                new LogicalOlapScan(new Table(0, "test", Table.TableType.OLAP, 
ImmutableList.of(
                     new Column("id", Type.INT),
                     new Column("name", Type.STRING)
                 )), Lists.newArrayList("test"))
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/plan/TestPlanOutput.java 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/plan/TestPlanOutput.java
index ec0df43660..cfea47f716 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/plan/TestPlanOutput.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/plan/TestPlanOutput.java
@@ -24,6 +24,7 @@ import org.apache.doris.catalog.Type;
 import org.apache.doris.nereids.analyzer.UnboundRelation;
 import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.operators.OperatorType;
+import org.apache.doris.nereids.operators.plans.logical.LogicalOlapScan;
 import org.apache.doris.nereids.operators.plans.logical.LogicalRelation;
 import org.apache.doris.nereids.operators.plans.physical.PhysicalScan;
 import org.apache.doris.nereids.trees.expressions.Expression;
@@ -47,7 +48,7 @@ public class TestPlanOutput implements Plans {
             new Column("name", Type.STRING, true, AggregateType.NONE, "", "")
         ));
         LogicalLeafPlan<LogicalRelation> relationPlan = plan(
-            new LogicalRelation(table, ImmutableList.of("a"))
+            new LogicalOlapScan(table, ImmutableList.of("a"))
         );
         List<Slot> output = relationPlan.getOutput();
         Assertions.assertEquals(2, output.size());
@@ -83,7 +84,7 @@ public class TestPlanOutput implements Plans {
             new Column("name", Type.STRING, true, AggregateType.NONE, "", "")
         ));
         LogicalLeafPlan<LogicalRelation> relationPlan = plan(
-            new LogicalRelation(table, ImmutableList.of("a"))
+            new LogicalOlapScan(table, ImmutableList.of("a"))
         );
 
         List<Slot> output = relationPlan.getOutput();
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjectionTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProjectTest.java
similarity index 93%
rename from 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjectionTest.java
rename to 
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProjectTest.java
index 84df7938dd..fbff548b8d 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectionToPhysicalProjectionTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/implementation/LogicalProjectToPhysicalProjectTest.java
@@ -37,13 +37,13 @@ import org.junit.Test;
 
 import java.util.List;
 
-public class LogicalProjectionToPhysicalProjectionTest implements Plans {
+public class LogicalProjectToPhysicalProjectTest implements Plans {
     @Test
     public void projectionImplTest(@Mocked Group group) {
         LogicalProject logicalProject = new 
LogicalProject(Lists.newArrayList());
         Plan plan = plan(logicalProject, new GroupPlan(group));
 
-        Rule<Plan> rule = new LogicalProjectionToPhysicalProjection().build();
+        Rule<Plan> rule = new LogicalProjectToPhysicalProject().build();
 
         PlannerContext plannerContext = new PlannerContext(new 
OptimizerContext(new Memo()), new ConnectContext(),
                 new PhysicalProperties());


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to