diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/OptimizerContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/OptimizerContext.java index d5ac07f27f..0b1605f230 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/OptimizerContext.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/OptimizerContext.java @@ -24,13 +24,12 @@ import org.apache.doris.nereids.jobs.scheduler.JobStack; import org.apache.doris.nereids.jobs.scheduler.SimpleJobScheduler; import org.apache.doris.nereids.memo.Memo; import org.apache.doris.nereids.rules.RuleSet; -import org.apache.doris.nereids.trees.TreeNode; /** * Context used in memo. */ -public class OptimizerContext> { - private final Memo memo; +public class OptimizerContext { + private final Memo memo; private RuleSet ruleSet; private JobPool jobPool; private final JobScheduler jobScheduler; @@ -40,7 +39,7 @@ public class OptimizerContext> { * * @param memo {@link Memo} reference */ - public OptimizerContext(Memo memo) { + public OptimizerContext(Memo memo) { this.memo = memo; this.ruleSet = new RuleSet(); this.jobPool = new JobStack(); @@ -63,7 +62,7 @@ public class OptimizerContext> { this.ruleSet = ruleSet; } - public Memo getMemo() { + public Memo getMemo() { return memo; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java index 31a87c9562..48ae896a3d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java @@ -23,7 +23,6 @@ import org.apache.doris.nereids.jobs.rewrite.RewriteBottomUpJob; import org.apache.doris.nereids.memo.Group; import org.apache.doris.nereids.memo.Memo; import org.apache.doris.nereids.properties.PhysicalProperties; -import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; import org.apache.doris.qe.ConnectContext; @@ -48,10 +47,10 @@ public class Planner { LogicalPlan plan, PhysicalProperties outputProperties, ConnectContext connectContext) throws AnalysisException { - Memo memo = new Memo<>(); + Memo memo = new Memo(); memo.initialize(plan); - OptimizerContext optimizerContext = new OptimizerContext<>(memo); + OptimizerContext optimizerContext = new OptimizerContext(memo); plannerContext = new PlannerContext(optimizerContext, connectContext, outputProperties); plannerContext.getOptimizerContext().pushJob( diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Unbound.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Unbound.java new file mode 100644 index 0000000000..a171d7ced5 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/Unbound.java @@ -0,0 +1,22 @@ +// 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.analyzer; + +/** Use to marking unbound plan and unbound expression. */ +public interface Unbound { +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundAlias.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundAlias.java index d7140292f4..15b4e61f94 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundAlias.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundAlias.java @@ -31,7 +31,7 @@ import java.util.List; */ public class UnboundAlias extends NamedExpression - implements UnaryExpression { + implements UnaryExpression, Unbound { public UnboundAlias(CHILD_TYPE child) { super(NodeType.UNBOUND_ALIAS, child); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java index 550894126d..a188ab01f5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java @@ -21,7 +21,10 @@ import org.apache.doris.nereids.analyzer.identifier.TableIdentifier; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.operators.plans.logical.LogicalLeafOperator; +import org.apache.doris.nereids.properties.LogicalProperties; +import org.apache.doris.nereids.properties.UnboundLogicalProperties; import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.util.Utils; import com.clearspring.analytics.util.Lists; @@ -32,7 +35,7 @@ import java.util.List; /** * Represent a relation plan node that has not been bound. */ -public class UnboundRelation extends LogicalLeafOperator { +public class UnboundRelation extends LogicalLeafOperator implements Unbound { private final List nameParts; public UnboundRelation(List nameParts) { @@ -64,9 +67,13 @@ public class UnboundRelation extends LogicalLeafOperator { } @Override - public List doComputeOutput() { - // fixme: throw unchecked exception - throw new IllegalStateException(new UnboundException("output")); + public LogicalProperties computeLogicalProperties(Plan... inputs) { + return new UnboundLogicalProperties(); + } + + @Override + public List computeOutput() { + throw new UnboundException("output"); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java index 5d1d4d7cbb..08ffcec866 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java @@ -28,7 +28,7 @@ import java.util.List; /** * Slot has not been bound. */ -public class UnboundSlot extends Slot { +public class UnboundSlot extends Slot implements Unbound { private final List nameParts; public UnboundSlot(List nameParts) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java index 11b8a54d3d..65b6cdbed1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java @@ -29,7 +29,7 @@ import java.util.List; /** * Star expression. */ -public class UnboundStar extends NamedExpression implements LeafExpression { +public class UnboundStar extends NamedExpression implements LeafExpression, Unbound { private final List target; public UnboundStar(List target) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/ApplyRuleJob.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/ApplyRuleJob.java index 5cf36a91ef..a48a17d590 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/ApplyRuleJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/ApplyRuleJob.java @@ -57,7 +57,7 @@ public class ApplyRuleJob extends Job { return; } - GroupExpressionMatching groupExpressionMatching + GroupExpressionMatching groupExpressionMatching = new GroupExpressionMatching(rule.getPattern(), groupExpression); for (Plan plan : groupExpressionMatching) { List newPlans = rule.transform(plan, context); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteBottomUpJob.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteBottomUpJob.java index b82ca9f280..a6048dfa0c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteBottomUpJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteBottomUpJob.java @@ -25,7 +25,7 @@ import org.apache.doris.nereids.memo.Group; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.pattern.GroupExpressionMatching; import org.apache.doris.nereids.rules.Rule; -import org.apache.doris.nereids.trees.TreeNode; +import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; @@ -35,16 +35,16 @@ import java.util.Objects; /** * Bottom up job for rewrite, use pattern match. */ -public class RewriteBottomUpJob> extends Job { +public class RewriteBottomUpJob extends Job { private final Group group; - private final List> rules; + private final List> rules; private final boolean childrenOptimized; - public RewriteBottomUpJob(Group group, List> rules, PlannerContext context) { + public RewriteBottomUpJob(Group group, List> rules, PlannerContext context) { this(group, rules, context, false); } - private RewriteBottomUpJob(Group group, List> rules, + private RewriteBottomUpJob(Group group, List> rules, PlannerContext context, boolean childrenOptimized) { super(JobType.BOTTOM_UP_REWRITE, context); this.group = Objects.requireNonNull(group, "group cannot be null"); @@ -57,23 +57,23 @@ public class RewriteBottomUpJob> extends J GroupExpression logicalExpression = group.getLogicalExpression(); if (!childrenOptimized) { for (Group childGroup : logicalExpression.children()) { - pushTask(new RewriteBottomUpJob<>(childGroup, rules, context, false)); + pushTask(new RewriteBottomUpJob(childGroup, rules, context, false)); } - pushTask(new RewriteBottomUpJob<>(group, rules, context, true)); + pushTask(new RewriteBottomUpJob(group, rules, context, true)); return; } - List> validRules = getValidRules(logicalExpression, rules); - for (Rule rule : validRules) { - GroupExpressionMatching groupExpressionMatching - = new GroupExpressionMatching<>(rule.getPattern(), logicalExpression); - for (NODE_TYPE before : groupExpressionMatching) { - List afters = rule.transform(before, context); + List> validRules = getValidRules(logicalExpression, rules); + for (Rule rule : validRules) { + GroupExpressionMatching groupExpressionMatching + = new GroupExpressionMatching(rule.getPattern(), logicalExpression); + for (Plan before : groupExpressionMatching) { + List afters = rule.transform(before, context); Preconditions.checkArgument(afters.size() == 1); - NODE_TYPE after = afters.get(0); + Plan after = afters.get(0); if (after != before) { context.getOptimizerContext().getMemo().copyIn(after, group, rule.isRewrite()); - pushTask(new RewriteBottomUpJob<>(group, rules, context, false)); + pushTask(new RewriteBottomUpJob(group, rules, context, false)); return; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteTopDownJob.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteTopDownJob.java index 64b348510d..4aebb3e182 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteTopDownJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/RewriteTopDownJob.java @@ -24,7 +24,7 @@ import org.apache.doris.nereids.memo.Group; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.pattern.GroupExpressionMatching; import org.apache.doris.nereids.rules.Rule; -import org.apache.doris.nereids.trees.TreeNode; +import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; @@ -34,9 +34,9 @@ import java.util.Objects; /** * Top down job for rewrite, use pattern match. */ -public class RewriteTopDownJob> extends Job { +public class RewriteTopDownJob extends Job { private final Group group; - private final List> rules; + private final List> rules; /** * Constructor. @@ -45,7 +45,7 @@ public class RewriteTopDownJob> extends Jo * @param rules rewrite rules * @param context planner context */ - public RewriteTopDownJob(Group group, List> rules, PlannerContext context) { + public RewriteTopDownJob(Group group, List> rules, PlannerContext context) { super(JobType.TOP_DOWN_REWRITE, context); this.group = Objects.requireNonNull(group, "group cannot be null"); this.rules = Objects.requireNonNull(rules, "rules cannot be null"); @@ -55,17 +55,17 @@ public class RewriteTopDownJob> extends Jo public void execute() { GroupExpression logicalExpression = group.getLogicalExpression(); - List> validRules = getValidRules(logicalExpression, rules); - for (Rule rule : validRules) { - GroupExpressionMatching groupExpressionMatching - = new GroupExpressionMatching<>(rule.getPattern(), logicalExpression); - for (NODE_TYPE before : groupExpressionMatching) { - List afters = rule.transform(before, context); + List> validRules = getValidRules(logicalExpression, rules); + for (Rule rule : validRules) { + GroupExpressionMatching groupExpressionMatching + = new GroupExpressionMatching(rule.getPattern(), logicalExpression); + for (Plan before : groupExpressionMatching) { + List afters = rule.transform(before, context); Preconditions.checkArgument(afters.size() == 1); - NODE_TYPE after = afters.get(0); + Plan after = afters.get(0); if (after != before) { context.getOptimizerContext().getMemo().copyIn(after, group, rule.isRewrite()); - pushTask(new RewriteTopDownJob<>(group, rules, context)); + pushTask(new RewriteTopDownJob(group, rules, context)); return; } } @@ -73,7 +73,7 @@ public class RewriteTopDownJob> extends Jo } for (Group childGroup : logicalExpression.children()) { - pushTask(new RewriteTopDownJob<>(childGroup, rules, context)); + pushTask(new RewriteTopDownJob(childGroup, rules, context)); } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java index ccbb6a072c..39fb09ae82 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java @@ -50,12 +50,13 @@ public class Group { * * @param groupExpression first {@link GroupExpression} in this Group */ - public Group(GroupExpression groupExpression) { + public Group(GroupExpression groupExpression, LogicalProperties logicalProperties) { if (groupExpression.getOperator() instanceof LogicalOperator) { this.logicalExpressions.add(groupExpression); } else { this.physicalExpressions.add(groupExpression); } + this.logicalProperties = logicalProperties; groupExpression.setParent(this); } @@ -101,12 +102,12 @@ public class Group { * @param newExpression new logical group expression * @return old logical group expression */ - public GroupExpression rewriteLogicalExpression( - GroupExpression newExpression) { - GroupExpression oldExpression = getLogicalExpression(); + public GroupExpression rewriteLogicalExpression(GroupExpression newExpression, + LogicalProperties logicalProperties) { logicalExpressions.clear(); logicalExpressions.add(newExpression); - return oldExpression; + this.logicalProperties = logicalProperties; + return getLogicalExpression(); } public double getCostLowerBound() { @@ -143,6 +144,10 @@ public class Group { return logicalProperties; } + public void setLogicalProperties(LogicalProperties logicalProperties) { + this.logicalProperties = logicalProperties; + } + public boolean isExplored() { return isExplored; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java index 1158e6550e..b73951b21f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java @@ -17,7 +17,7 @@ package org.apache.doris.nereids.memo; -import org.apache.doris.nereids.trees.TreeNode; +import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.plans.Plan; @@ -30,16 +30,14 @@ import java.util.Map; /** * Representation for memo in cascades optimizer. - * - * @param should be {@link Plan} or {@link Expression} */ -public class Memo> { +public class Memo { private final List groups = Lists.newArrayList(); // we could not use Set, because Set has no get method. private final Map groupExpressions = Maps.newHashMap(); private Group root; - public void initialize(NODE_TYPE node) { + public void initialize(Plan node) { root = copyIn(node, null, false).getParent(); } @@ -56,10 +54,10 @@ public class Memo> { * @param rewrite whether to rewrite the node to the target group * @return Reference of node in Memo */ - public GroupExpression copyIn(NODE_TYPE node, Group target, boolean rewrite) { + public GroupExpression copyIn(Plan node, Group target, boolean rewrite) { Preconditions.checkArgument(!rewrite || target != null); List childrenGroups = Lists.newArrayList(); - for (NODE_TYPE child : node.children()) { + for (Plan child : node.children()) { childrenGroups.add(copyIn(child, null, rewrite).getParent()); } if (node.getGroupExpression().isPresent() && groupExpressions.containsKey(node.getGroupExpression().get())) { @@ -67,7 +65,7 @@ public class Memo> { } GroupExpression newGroupExpression = new GroupExpression(node.getOperator()); newGroupExpression.setChildren(childrenGroups); - return insertOrRewriteGroupExpression(newGroupExpression, target, rewrite); + return insertOrRewriteGroupExpression(newGroupExpression, target, rewrite, node.getLogicalProperties()); // TODO: need to derive logical property if generate new group. currently we not copy logical plan into } @@ -82,8 +80,8 @@ public class Memo> { * @param rewrite whether to rewrite the groupExpression to target group * @return existing groupExpression in memo or newly generated groupExpression */ - private GroupExpression insertOrRewriteGroupExpression( - GroupExpression groupExpression, Group target, boolean rewrite) { + private GroupExpression insertOrRewriteGroupExpression(GroupExpression groupExpression, Group target, + boolean rewrite, LogicalProperties logicalProperties) { GroupExpression existedGroupExpression = groupExpressions.get(groupExpression); if (existedGroupExpression != null) { if (target != null && !target.getGroupId().equals(existedGroupExpression.getParent().getGroupId())) { @@ -93,13 +91,13 @@ public class Memo> { } if (target != null) { if (rewrite) { - GroupExpression oldExpression = target.rewriteLogicalExpression(groupExpression); + GroupExpression oldExpression = target.rewriteLogicalExpression(groupExpression, logicalProperties); groupExpressions.remove(oldExpression); } else { target.addGroupExpression(groupExpression); } } else { - Group group = new Group(groupExpression); + Group group = new Group(groupExpression, logicalProperties); Preconditions.checkArgument(!groups.contains(group), "new group with already exist output"); groups.add(group); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java index f2ddc06716..10bb5c9347 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/OperatorType.java @@ -34,6 +34,7 @@ public enum OperatorType { LOGICAL_PROJECT, LOGICAL_FILTER, LOGICAL_JOIN, + PLACE_HOLDER, // physical plan PHYSICAL_OLAP_SCAN, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalBinaryOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalBinaryOperator.java index 228ee08358..fc7d3a9a6f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalBinaryOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalBinaryOperator.java @@ -27,7 +27,10 @@ import org.apache.doris.nereids.trees.plans.PlaceHolderPlan; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.logical.LogicalBinaryPlan; +import com.google.common.base.Preconditions; + import java.util.List; +import java.util.Optional; /** * Abstract class for all logical binary operator that have two inputs. @@ -40,16 +43,20 @@ public abstract class LogicalBinaryOperator extends AbstractOperator } @Override - public final List computeOutput(Plan... inputs) { - return doComputeOutput(inputs[0], inputs[1]); + public final LogicalProperties computeLogicalProperties(Plan... inputs) { + Preconditions.checkArgument(inputs.length == 2); + return new LogicalProperties(computeOutput(inputs[0], inputs[1])); } - public abstract List doComputeOutput(Plan left, Plan right); + public abstract List computeOutput(Plan left, Plan right); @Override public LogicalBinaryPlan toTreeNode(GroupExpression groupExpression) { LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); - return new LogicalBinaryPlan(this, groupExpression, logicalProperties, - new PlaceHolderPlan(), new PlaceHolderPlan()); + LogicalProperties leftChildProperties = groupExpression.child(0).getLogicalProperties(); + LogicalProperties rightChildProperties = groupExpression.child(1).getLogicalProperties(); + return new LogicalBinaryPlan(this, Optional.of(groupExpression), Optional.of(logicalProperties), + new PlaceHolderPlan(leftChildProperties), new PlaceHolderPlan(rightChildProperties) + ); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalFilter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalFilter.java index c7d579898c..6b61dd36ea 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalFilter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalFilter.java @@ -43,7 +43,7 @@ public class LogicalFilter extends LogicalUnaryOperator { @Override - public List doComputeOutput(Plan input) { + public List computeOutput(Plan input) { return input.getOutput(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalJoin.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalJoin.java index b1672627bd..8ed6c6e1b7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalJoin.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalJoin.java @@ -71,7 +71,7 @@ public class LogicalJoin extends LogicalBinaryOperator { } @Override - public List doComputeOutput(Plan leftInput, Plan rightInput) { + public List computeOutput(Plan leftInput, Plan rightInput) { switch (joinType) { case LEFT_SEMI_JOIN: return ImmutableList.copyOf(leftInput.getOutput()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalLeafOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalLeafOperator.java index 44c72f06e6..0e872c9f49 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalLeafOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalLeafOperator.java @@ -21,11 +21,15 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.AbstractOperator; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.operators.plans.LeafPlanOperator; +import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan; +import com.google.common.base.Preconditions; + import java.util.List; +import java.util.Optional; /** * Abstract class for all logical operator that have no input. @@ -38,14 +42,16 @@ public abstract class LogicalLeafOperator extends AbstractOperator } @Override - public final List computeOutput(Plan... inputs) { - return doComputeOutput(); + public LogicalProperties computeLogicalProperties(Plan... inputs) { + Preconditions.checkArgument(inputs.length == 0); + return new LogicalProperties(computeOutput()); } - public abstract List doComputeOutput(); + public abstract List computeOutput(); @Override public LogicalLeafPlan toTreeNode(GroupExpression groupExpression) { - return new LogicalLeafPlan(this, groupExpression, groupExpression.getParent().getLogicalProperties()); + LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); + return new LogicalLeafPlan(this, Optional.of(groupExpression), Optional.of(logicalProperties)); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOperator.java index 0421f8f159..0e38c86d0c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalOperator.java @@ -18,14 +18,12 @@ package org.apache.doris.nereids.operators.plans.logical; import org.apache.doris.nereids.operators.plans.PlanOperator; -import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.plans.Plan; -import java.util.List; - /** * interface for all concrete logical plan operator. */ public interface LogicalOperator extends PlanOperator { - List computeOutput(Plan... inputs); + LogicalProperties computeLogicalProperties(Plan... inputs); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalProject.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalProject.java index 5554542443..a9ba14d74a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalProject.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalProject.java @@ -56,7 +56,7 @@ public class LogicalProject extends LogicalUnaryOperator { } @Override - public List doComputeOutput(Plan input) { + public List computeOutput(Plan input) { // fixme: not throw a checked exception return projects.stream() .map(namedExpr -> { 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 6f01817b82..baa1835f91 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 @@ -62,7 +62,7 @@ public class LogicalRelation extends LogicalLeafOperator { } @Override - public List doComputeOutput() { + public List computeOutput() { return table.getBaseSchema() .stream() .map(col -> SlotReference.fromColumn(col, qualifier)) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalUnaryOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalUnaryOperator.java index b04f2ae8f3..cb3ee3cf68 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalUnaryOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/logical/LogicalUnaryOperator.java @@ -27,7 +27,10 @@ import org.apache.doris.nereids.trees.plans.PlaceHolderPlan; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.logical.LogicalUnaryPlan; +import com.google.common.base.Preconditions; + import java.util.List; +import java.util.Optional; /** * Abstract class for all logical operator that have one input. @@ -40,15 +43,19 @@ public abstract class LogicalUnaryOperator extends AbstractOperator } @Override - public final List computeOutput(Plan... inputs) { - return doComputeOutput(inputs[0]); + public LogicalProperties computeLogicalProperties(Plan... inputs) { + Preconditions.checkArgument(inputs.length == 1); + return new LogicalProperties(computeOutput(inputs[0])); } - public abstract List doComputeOutput(Plan input); + public abstract List computeOutput(Plan input); @Override public LogicalUnaryPlan toTreeNode(GroupExpression groupExpression) { LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); - return new LogicalUnaryPlan(this, groupExpression, logicalProperties, new PlaceHolderPlan()); + LogicalProperties childProperties = groupExpression.child(0).getLogicalProperties(); + return new LogicalUnaryPlan(this, Optional.of(groupExpression), + Optional.of(logicalProperties), new PlaceHolderPlan(childProperties) + ); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalBinaryOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalBinaryOperator.java index 813cb3d445..c34c6d25ec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalBinaryOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalBinaryOperator.java @@ -22,12 +22,10 @@ import org.apache.doris.nereids.operators.AbstractOperator; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.operators.plans.BinaryPlanOperator; import org.apache.doris.nereids.properties.LogicalProperties; -import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.PlaceHolderPlan; -import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.physical.PhysicalBinaryPlan; -import java.util.List; +import java.util.Optional; /** * Abstract class for all physical operator that have two inputs. @@ -39,19 +37,13 @@ public abstract class PhysicalBinaryOperator extends AbstractOperator super(type); } - @Override - public final List computeOutputs(LogicalProperties logicalProperties, Plan... inputs) { - return doComputeOutput(logicalProperties, inputs[0], inputs[1]); - } - - public List doComputeOutput(LogicalProperties logicalProperties, Plan left, Plan right) { - return logicalProperties.getOutput(); - } - @Override public PhysicalBinaryPlan toTreeNode(GroupExpression groupExpression) { LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); - return new PhysicalBinaryPlan(this, groupExpression, logicalProperties, - new PlaceHolderPlan(), new PlaceHolderPlan()); + LogicalProperties leftChildProperties = groupExpression.child(0).getLogicalProperties(); + LogicalProperties rightChildProperties = groupExpression.child(1).getLogicalProperties(); + return new PhysicalBinaryPlan(this, Optional.of(groupExpression), logicalProperties, + new PlaceHolderPlan(leftChildProperties), new PlaceHolderPlan(rightChildProperties) + ); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalLeafOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalLeafOperator.java index 6cf64ede7c..fda9e7e600 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalLeafOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalLeafOperator.java @@ -22,11 +22,9 @@ import org.apache.doris.nereids.operators.AbstractOperator; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.operators.plans.LeafPlanOperator; import org.apache.doris.nereids.properties.LogicalProperties; -import org.apache.doris.nereids.trees.expressions.Slot; -import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.physical.PhysicalLeafPlan; -import java.util.List; +import java.util.Optional; /** * Abstract class for all physical operator that have no input. @@ -38,17 +36,9 @@ public abstract class PhysicalLeafOperator extends AbstractOperator super(type); } - @Override - public final List computeOutputs(LogicalProperties logicalProperties, Plan... inputs) { - return doComputeOutput(logicalProperties); - } - - public List doComputeOutput(LogicalProperties logicalProperties) { - return logicalProperties.getOutput(); - } - @Override public PhysicalLeafPlan toTreeNode(GroupExpression groupExpression) { - return new PhysicalLeafPlan(this, groupExpression, groupExpression.getParent().getLogicalProperties()); + LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); + return new PhysicalLeafPlan(this, Optional.of(groupExpression), logicalProperties); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalOperator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalOperator.java index 8414f6356d..3f0777e6db 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalOperator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/operators/plans/physical/PhysicalOperator.java @@ -18,17 +18,9 @@ package org.apache.doris.nereids.operators.plans.physical; import org.apache.doris.nereids.operators.plans.PlanOperator; -import org.apache.doris.nereids.properties.LogicalProperties; -import org.apache.doris.nereids.trees.expressions.Slot; -import org.apache.doris.nereids.trees.plans.Plan; - -import java.util.List; /** * interface for all concrete physical operator. */ public interface PhysicalOperator extends PlanOperator { - - List computeOutputs(LogicalProperties logicalProperties, Plan... inputs); - } 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 daecac8191..7c479bc8ed 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 @@ -22,12 +22,10 @@ import org.apache.doris.nereids.operators.AbstractOperator; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.operators.plans.UnaryPlanOperator; import org.apache.doris.nereids.properties.LogicalProperties; -import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.PlaceHolderPlan; -import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.physical.PhysicalUnaryPlan; -import java.util.List; +import java.util.Optional; /** * Abstract class for all physical operator that have one input. @@ -39,18 +37,12 @@ public abstract class PhysicalUnaryOperator extends AbstractOperator super(type); } - @Override - public final List computeOutputs(LogicalProperties logicalProperties, Plan... inputs) { - return doComputeOutput(logicalProperties, inputs[0]); - } - - public List doComputeOutput(LogicalProperties logicalProperties, Plan input) { - return logicalProperties.getOutput(); - } - @Override public PhysicalUnaryPlan toTreeNode(GroupExpression groupExpression) { LogicalProperties logicalProperties = groupExpression.getParent().getLogicalProperties(); - return new PhysicalUnaryPlan(this, groupExpression, logicalProperties, new PlaceHolderPlan()); + LogicalProperties childProperties = groupExpression.child(0).getLogicalProperties(); + return new PhysicalUnaryPlan(this, Optional.of(groupExpression), + logicalProperties, new PlaceHolderPlan(childProperties) + ); } } 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 c70b8a4dc4..c90524f3ce 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 @@ -229,7 +229,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { if (left == null) { left = right; } else { - left = new LogicalBinaryPlan(new LogicalJoin(JoinType.INNER_JOIN, null), left, right); + left = new LogicalBinaryPlan( + new LogicalJoin(JoinType.INNER_JOIN, Optional.empty()), left, right); } left = withJoinRelations(left, relation); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupExpressionMatching.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupExpressionMatching.java index 955665a18b..8da0ba8cde 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupExpressionMatching.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupExpressionMatching.java @@ -19,6 +19,7 @@ package org.apache.doris.nereids.pattern; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.trees.TreeNode; +import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.collect.Lists; @@ -32,17 +33,17 @@ import java.util.Objects; * TODO: adapt ANY and MULTI * TODO: add ut */ -public class GroupExpressionMatching> implements Iterable { - private final Pattern pattern; +public class GroupExpressionMatching implements Iterable { + private final Pattern pattern; private final GroupExpression groupExpression; - public GroupExpressionMatching(Pattern pattern, GroupExpression groupExpression) { + public GroupExpressionMatching(Pattern pattern, GroupExpression groupExpression) { this.pattern = Objects.requireNonNull(pattern); this.groupExpression = Objects.requireNonNull(groupExpression); } @Override - public GroupExpressionIterator iterator() { + public GroupExpressionIterator iterator() { return new GroupExpressionIterator<>(pattern, groupExpression); } @@ -97,7 +98,7 @@ public class GroupExpressionMatching> impl for (int i = 0; i < childrenResults.size(); i++) { children.add(childrenResults.get(i).get(childrenResultsIndex[i])); } - NODE_TYPE result = root.newChildren(children); + NODE_TYPE result = root.withChildren(children); results.add(result); offset = 0; while (true) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupMatching.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupMatching.java index 4771300ad9..ef22b4837d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupMatching.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/GroupMatching.java @@ -21,6 +21,7 @@ import org.apache.doris.nereids.memo.Group; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.OperatorType; import org.apache.doris.nereids.trees.TreeNode; +import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.collect.Lists; @@ -59,18 +60,18 @@ public class GroupMatching implements Iterable pattern, Group group) { + public GroupIterator(Pattern pattern, Group group) { this.pattern = pattern; this.iterator = Lists.newArrayList(); for (GroupExpression groupExpression : group.getLogicalExpressions()) { - GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator = + GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator = new GroupExpressionMatching(pattern, groupExpression).iterator(); if (groupExpressionIterator.hasNext()) { this.iterator.add(groupExpressionIterator); } } for (GroupExpression groupExpression : group.getPhysicalExpressions()) { - GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator = + GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator = new GroupExpressionMatching(pattern, groupExpression).iterator(); if (groupExpressionIterator.hasNext()) { this.iterator.add(groupExpressionIterator); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/Pattern.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/Pattern.java index 781e10aa97..009a92c934 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/Pattern.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/Pattern.java @@ -161,7 +161,8 @@ public class Pattern newChildren(List> children) { + public Pattern withChildren( + List> children) { throw new RuntimeException(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/generator/JavaAstBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/generator/JavaAstBuilder.java index 069b2dd4cb..6ccbdf5f6a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/generator/JavaAstBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/pattern/generator/JavaAstBuilder.java @@ -206,9 +206,9 @@ public class JavaAstBuilder extends JavaParserBaseVisitor { } else if (memberCtx.methodDeclaration() != null) { methodDeclarations.add(visitMethodDeclaration(memberCtx.methodDeclaration())); } + // find inner class + memberCtx.accept(this); } - // find inner class - memberCtx.accept(this); } String className = getText(ctx.identifier()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java index 80af9bcd59..078ece11d7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/LogicalProperties.java @@ -36,4 +36,8 @@ public class LogicalProperties { public List getOutput() { return output; } + + public LogicalProperties withOutput(List output) { + return new LogicalProperties(output); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/UnboundLogicalProperties.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/UnboundLogicalProperties.java new file mode 100644 index 0000000000..3ea3234f1a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/UnboundLogicalProperties.java @@ -0,0 +1,40 @@ +// 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.properties; + +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.expressions.Slot; + +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * LogicalPlanOperator must compute and return non-null LogicalProperties without exception, + * so UnboundRelation.computeLogicalProperties() return a UnboundLogicalProperties temporary. + */ +public class UnboundLogicalProperties extends LogicalProperties { + public UnboundLogicalProperties() { + super(ImmutableList.of()); + } + + @Override + public List getOutput() { + throw new UnboundException("output"); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/AbstractTreeNode.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/AbstractTreeNode.java index 16cbaf9f44..d4f00a3406 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/AbstractTreeNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/AbstractTreeNode.java @@ -24,6 +24,7 @@ import org.apache.doris.nereids.operators.Operator; import com.google.common.collect.ImmutableList; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -43,7 +44,7 @@ public abstract class AbstractTreeNode> public AbstractTreeNode(NodeType type, NODE_TYPE... children) { - this(type, null, children); + this(type, Optional.empty(), children); } /** @@ -53,10 +54,10 @@ public abstract class AbstractTreeNode> * @param groupExpression group expression related to the operator of this node * @param children children of this node */ - public AbstractTreeNode(NodeType type, GroupExpression groupExpression, NODE_TYPE... children) { + public AbstractTreeNode(NodeType type, Optional groupExpression, NODE_TYPE... children) { this.type = type; this.children = ImmutableList.copyOf(children); - this.groupExpression = Optional.ofNullable(groupExpression); + this.groupExpression = Objects.requireNonNull(groupExpression, "groupExpression can not be null"); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TreeNode.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TreeNode.java index 12a8597782..6844607d6c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TreeNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/TreeNode.java @@ -44,5 +44,5 @@ public interface TreeNode> { int arity(); - NODE_TYPE newChildren(List children); + NODE_TYPE withChildren(List children); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/EqualTo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/EqualTo.java index 4f561e525f..c60219e9ad 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/EqualTo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/EqualTo.java @@ -45,7 +45,7 @@ public class EqualTo newChildren(List children) { + public EqualTo withChildren(List children) { Preconditions.checkArgument(children.size() == 2); return new EqualTo<>(children.get(0), children.get(1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java index 7a275e4b2b..5b0d71e522 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java @@ -61,7 +61,7 @@ public abstract class Expression extends AbstractTreeNode { } @Override - public Expression newChildren(List children) { + public Expression withChildren(List children) { throw new RuntimeException(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThan.java index 7e0e291366..2b1ea60efd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThan.java @@ -50,7 +50,7 @@ public class GreaterThan newChildren(List children) { + public GreaterThan withChildren(List children) { Preconditions.checkArgument(children.size() == 2); return new GreaterThan<>(children.get(0), children.get(1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThanEqual.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThanEqual.java index 2ca42bbb26..75e50feed0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThanEqual.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/GreaterThanEqual.java @@ -50,7 +50,7 @@ public class GreaterThanEqual newChildren(List children) { + public GreaterThanEqual withChildren(List children) { Preconditions.checkArgument(children.size() == 2); return new GreaterThanEqual<>(children.get(0), children.get(1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThan.java index 3cdaa4abaf..447fc9f499 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThan.java @@ -50,7 +50,7 @@ public class LessThan newChildren(List children) { + public LessThan withChildren(List children) { Preconditions.checkArgument(children.size() == 2); return new LessThan<>(children.get(0), children.get(1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThanEqual.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThanEqual.java index f38dc8a8c1..a0fe0be7a5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThanEqual.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/LessThanEqual.java @@ -50,7 +50,7 @@ public class LessThanEqual newChildren(List children) { + public LessThanEqual withChildren(List children) { Preconditions.checkArgument(children.size() == 2); return new LessThanEqual<>(children.get(0), children.get(1)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Not.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Not.java index a7a38e56ea..06ea928895 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Not.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Not.java @@ -47,7 +47,7 @@ public class Not extends Expression } @Override - public Not newChildren(List children) { + public Not withChildren(List children) { Preconditions.checkArgument(children.size() == 1); return new Not<>(children.get(0)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java index ff6cd109cc..b1f13694b9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/AbstractPlan.java @@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.plans; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.PlanOperator; +import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.AbstractTreeNode; import org.apache.doris.nereids.trees.NodeType; @@ -27,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * Abstract class for all concrete plan node. @@ -36,14 +38,18 @@ public abstract class AbstractPlan public final OP_TYPE operator; - public AbstractPlan(NodeType type, OP_TYPE operator, Plan... children) { - super(type, children); - this.operator = Objects.requireNonNull(operator, "operator can not be null"); + protected final LogicalProperties logicalProperties; + + public AbstractPlan(NodeType type, OP_TYPE operator, LogicalProperties logicalProperties, Plan... children) { + this(type, operator, Optional.empty(), logicalProperties, children); } - public AbstractPlan(NodeType type, OP_TYPE operator, GroupExpression groupExpression, Plan... children) { + /** all parameter constructor. */ + public AbstractPlan(NodeType type, OP_TYPE operator, Optional groupExpression, + LogicalProperties logicalProperties, Plan... children) { super(type, groupExpression, children); this.operator = Objects.requireNonNull(operator, "operator can not be null"); + this.logicalProperties = Objects.requireNonNull(logicalProperties, "logicalProperties can not be null"); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlaceHolderPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlaceHolderPlan.java index d1a325072f..24047896ed 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlaceHolderPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlaceHolderPlan.java @@ -18,12 +18,17 @@ package org.apache.doris.nereids.trees.plans; import org.apache.doris.nereids.memo.GroupExpression; -import org.apache.doris.nereids.operators.plans.LeafPlanOperator; +import org.apache.doris.nereids.operators.OperatorType; +import org.apache.doris.nereids.operators.plans.logical.LogicalLeafOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan; + +import com.google.common.base.Preconditions; import java.util.List; +import java.util.Objects; import java.util.Optional; /** @@ -31,7 +36,30 @@ import java.util.Optional; * Used in {@link org.apache.doris.nereids.pattern.GroupExpressionMatching.GroupExpressionIterator}, * as a place-holder when do match root. */ -public class PlaceHolderPlan implements LeafPlan { +public class PlaceHolderPlan extends LogicalLeafPlan { + /** PlaceHolderOperator. */ + public static class PlaceHolderOperator extends LogicalLeafOperator { + private final LogicalProperties logicalProperties; + + public PlaceHolderOperator(LogicalProperties logicalProperties) { + super(OperatorType.PLACE_HOLDER); + this.logicalProperties = Objects.requireNonNull(logicalProperties, "logicalProperties can not be null"); + } + + @Override + public List computeOutput() { + throw new IllegalStateException("PlaceholderOperator can not compute output"); + } + + @Override + public LogicalProperties computeLogicalProperties(Plan... inputs) { + throw new IllegalStateException("PlaceholderOperator can not compute logical properties"); + } + } + + public PlaceHolderPlan(LogicalProperties logicalProperties) { + super(new PlaceHolderOperator(logicalProperties), Optional.empty(), Optional.of(logicalProperties)); + } @Override public Optional getGroupExpression() { @@ -44,37 +72,13 @@ public class PlaceHolderPlan implements LeafPlan { } @Override - public Plan newChildren(List children) { + public PlaceHolderPlan withOutput(List output) { throw new RuntimeException(); } @Override - public LeafPlanOperator getOperator() { - throw new RuntimeException(); - } - - @Override - public LogicalProperties getLogicalProperties() { - throw new RuntimeException(); - } - - @Override - public List getOutput() { - throw new RuntimeException(); - } - - @Override - public String treeString() { - throw new RuntimeException(); - } - - @Override - public List children() { - throw new RuntimeException(); - } - - @Override - public Plan child(int index) { - throw new RuntimeException(); + public PlaceHolderPlan withChildren(List children) { + Preconditions.checkArgument(children.size() == 0); + return new PlaceHolderPlan(logicalProperties); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java index ff7b26d617..cb899d7257 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/Plan.java @@ -37,4 +37,5 @@ public interface Plan extends TreeNode { String treeString(); + Plan withOutput(List output); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/AbstractLogicalPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/AbstractLogicalPlan.java index 780dcbb59c..f790829bba 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/AbstractLogicalPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/AbstractLogicalPlan.java @@ -25,8 +25,8 @@ import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.AbstractPlan; import org.apache.doris.nereids.trees.plans.Plan; -import java.util.Collections; import java.util.List; +import java.util.Optional; /** * Abstract class for all concrete logical plan. @@ -34,17 +34,19 @@ import java.util.List; public abstract class AbstractLogicalPlan extends AbstractPlan implements LogicalPlan { - protected final LogicalProperties logicalProperties; - public AbstractLogicalPlan(NodeType type, OP_TYPE operator, Plan... children) { - super(type, operator, children); - this.logicalProperties = new LogicalProperties(Collections.emptyList()); + super(type, operator, operator.computeLogicalProperties(children), children); } public AbstractLogicalPlan(NodeType type, OP_TYPE operator, - GroupExpression groupExpression, LogicalProperties logicalProperties, Plan... children) { - super(type, operator, groupExpression, children); - this.logicalProperties = logicalProperties; + Optional logicalProperties, Plan... children) { + super(type, operator, logicalProperties.orElseGet(() -> operator.computeLogicalProperties(children)), children); + } + + public AbstractLogicalPlan(NodeType type, OP_TYPE operator, Optional groupExpression, + Optional logicalProperties, Plan... children) { + super(type, operator, groupExpression, + logicalProperties.orElseGet(() -> operator.computeLogicalProperties(children)), children); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalBinaryPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalBinaryPlan.java index 8d860b9dd7..c7cfbd2bf3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalBinaryPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalBinaryPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.logical.LogicalBinaryOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.BinaryPlan; import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all logical plan that have two children. @@ -39,18 +41,29 @@ public class LogicalBinaryPlan< implements BinaryPlan { public LogicalBinaryPlan(OP_TYPE operator, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { - super(NodeType.LOGICAL, operator, leftChild, rightChild); + super(NodeType.LOGICAL, operator, Optional.empty(), leftChild, rightChild); } - public LogicalBinaryPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties, - LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { + public LogicalBinaryPlan(OP_TYPE operator, Optional logicalProperties, + LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { + super(NodeType.LOGICAL, operator, logicalProperties, leftChild, rightChild); + } + + public LogicalBinaryPlan(OP_TYPE operator, Optional groupExpression, + Optional logicalProperties, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { super(NodeType.LOGICAL, operator, groupExpression, logicalProperties, leftChild, rightChild); } @Override - public LogicalBinaryPlan newChildren(List children) { + public LogicalBinaryPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 2); - return new LogicalBinaryPlan(operator, groupExpression.orElse(null), - logicalProperties, children.get(0), children.get(1)); + return new LogicalBinaryPlan(operator, groupExpression, Optional.empty(), + children.get(0), children.get(1)); + } + + @Override + public LogicalBinaryPlan withOutput(List output) { + return new LogicalBinaryPlan<>(operator, groupExpression, + Optional.of(logicalProperties.withOutput(output)), left(), right()); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalLeafPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalLeafPlan.java index 012424125e..9fe4e55bcd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalLeafPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalLeafPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.logical.LogicalLeafOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.LeafPlan; import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all logical plan that have no child. @@ -39,13 +41,24 @@ public class LogicalLeafPlan super(NodeType.LOGICAL, operator); } - public LogicalLeafPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties) { + public LogicalLeafPlan(OP_TYPE operator, Optional logicalProperties) { + super(NodeType.LOGICAL, operator, logicalProperties); + } + + public LogicalLeafPlan(OP_TYPE operator, Optional groupExpression, + Optional logicalProperties) { super(NodeType.LOGICAL, operator, groupExpression, logicalProperties); } @Override - public LogicalLeafPlan newChildren(List children) { + public LogicalLeafPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 0); - return new LogicalLeafPlan(operator, groupExpression.orElse(null), logicalProperties); + return new LogicalLeafPlan(operator, groupExpression, Optional.empty()); + } + + @Override + public LogicalLeafPlan withOutput(List output) { + return new LogicalLeafPlan<>(operator, groupExpression, + Optional.of(logicalProperties.withOutput(output))); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlan.java index 3cb4341a6e..db19a062a6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlan.java @@ -32,7 +32,7 @@ public interface LogicalPlan extends Plan { LogicalOperator getOperator(); @Override - LogicalPlan newChildren(List children); + LogicalPlan withChildren(List children); /** * Map a [[LogicalPlan]] to another [[LogicalPlan]] if the passed context exists using the diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnaryPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnaryPlan.java index b44db32de2..a12c243ff6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnaryPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnaryPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.logical.LogicalUnaryOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.UnaryPlan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all logical plan that have one child. @@ -39,14 +41,20 @@ public class LogicalUnaryPlan groupExpression, + Optional logicalProperties, CHILD_TYPE child) { super(NodeType.LOGICAL, operator, groupExpression, logicalProperties, child); } @Override - public LogicalUnaryPlan newChildren(List children) { + public LogicalUnaryPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 1); - return new LogicalUnaryPlan(operator, groupExpression.orElse(null), logicalProperties, children.get(0)); + return new LogicalUnaryPlan(operator, groupExpression, Optional.empty(), children.get(0)); + } + + @Override + public LogicalUnaryPlan withOutput(List output) { + return new LogicalUnaryPlan<>(operator, groupExpression, + Optional.of(logicalProperties.withOutput(output)), child()); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java index ddd0228250..736b1d2196 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java @@ -27,7 +27,7 @@ import org.apache.doris.nereids.trees.plans.AbstractPlan; import org.apache.doris.nereids.trees.plans.Plan; import java.util.List; -import java.util.Objects; +import java.util.Optional; /** * Abstract class for all concrete physical plan. @@ -36,7 +36,6 @@ public abstract class AbstractPhysicalPlan extends AbstractPlan implements PhysicalPlan { - protected final LogicalProperties logicalProperties; protected final PhysicalProperties physicalProperties; /** @@ -44,8 +43,7 @@ public abstract class AbstractPhysicalPlan */ public AbstractPhysicalPlan(NodeType type, OP_TYPE operator, LogicalProperties logicalProperties, Plan... children) { - super(type, operator, children); - this.logicalProperties = Objects.requireNonNull(logicalProperties, "logicalProperties can not be null"); + super(type, operator, logicalProperties, children); // TODO: compute physical properties this.physicalProperties = new PhysicalProperties(); } @@ -59,10 +57,9 @@ public abstract class AbstractPhysicalPlan * @param logicalProperties logical properties of this plan * @param children children of this plan */ - public AbstractPhysicalPlan(NodeType type, OP_TYPE operator, GroupExpression groupExpression, + public AbstractPhysicalPlan(NodeType type, OP_TYPE operator, Optional groupExpression, LogicalProperties logicalProperties, Plan... children) { - super(type, operator, groupExpression, children); - this.logicalProperties = Objects.requireNonNull(logicalProperties, "logicalProperties can not be null"); + super(type, operator, groupExpression, logicalProperties, children); // TODO: compute physical properties this.physicalProperties = new PhysicalProperties(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalBinaryPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalBinaryPlan.java index 9b95552216..aba0e86e7b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalBinaryPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalBinaryPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.physical.PhysicalBinaryOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.BinaryPlan; import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all physical plan that have two children. @@ -43,15 +45,21 @@ public class PhysicalBinaryPlan< super(NodeType.PHYSICAL, operator, logicalProperties, leftChild, rightChild); } - public PhysicalBinaryPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties, - LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { + public PhysicalBinaryPlan(OP_TYPE operator, Optional groupExpression, + LogicalProperties logicalProperties, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) { super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties, leftChild, rightChild); } @Override - public PhysicalBinaryPlan newChildren(List children) { + public PhysicalBinaryPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 2); - return new PhysicalBinaryPlan(operator, groupExpression.orElse(null), logicalProperties, - children.get(0), children.get(1)); + return new PhysicalBinaryPlan(operator, groupExpression, logicalProperties, + children.get(0), children.get(1)); + } + + @Override + public PhysicalBinaryPlan withOutput(List output) { + LogicalProperties logicalProperties = new LogicalProperties(output); + return new PhysicalBinaryPlan<>(operator, groupExpression, logicalProperties, left(), right()); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLeafPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLeafPlan.java index 0408641b79..75bb1abea8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLeafPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalLeafPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.physical.PhysicalLeafOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.LeafPlan; import org.apache.doris.nereids.trees.plans.Plan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all physical plan that have no child. @@ -39,13 +41,20 @@ public class PhysicalLeafPlan super(NodeType.PHYSICAL, operator, logicalProperties); } - public PhysicalLeafPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties) { + public PhysicalLeafPlan(OP_TYPE operator, Optional groupExpression, + LogicalProperties logicalProperties) { super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties); } @Override - public PhysicalLeafPlan newChildren(List children) { + public PhysicalLeafPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 0); - return new PhysicalLeafPlan(operator, groupExpression.orElse(null), logicalProperties); + return new PhysicalLeafPlan(operator, groupExpression, logicalProperties); + } + + @Override + public PhysicalLeafPlan withOutput(List output) { + LogicalProperties logicalProperties = new LogicalProperties(output); + return new PhysicalLeafPlan<>(operator, groupExpression, logicalProperties); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalUnaryPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalUnaryPlan.java index caadb0c177..b113458b6c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalUnaryPlan.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalUnaryPlan.java @@ -21,12 +21,14 @@ import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.operators.plans.physical.PhysicalUnaryOperator; import org.apache.doris.nereids.properties.LogicalProperties; import org.apache.doris.nereids.trees.NodeType; +import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.UnaryPlan; import com.google.common.base.Preconditions; import java.util.List; +import java.util.Optional; /** * Abstract class for all physical plan that have one child. @@ -39,15 +41,20 @@ public class PhysicalUnaryPlan groupExpression, + LogicalProperties logicalProperties, CHILD_TYPE child) { super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties, child); } @Override - public PhysicalUnaryPlan newChildren(List children) { + public PhysicalUnaryPlan withChildren(List children) { Preconditions.checkArgument(children.size() == 1); - return new PhysicalUnaryPlan(operator, groupExpression.orElse(null), - logicalProperties, (Plan) children.get(0)); + return new PhysicalUnaryPlan(operator, groupExpression, logicalProperties, children.get(0)); + } + + @Override + public PhysicalUnaryPlan withOutput(List output) { + LogicalProperties logicalProperties = new LogicalProperties(output); + return new PhysicalUnaryPlan<>(operator, groupExpression, logicalProperties, child()); } } 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 b5e5fba18f..43d454c627 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 @@ -17,7 +17,9 @@ package org.apache.doris.nereids.jobs; -import org.apache.doris.catalog.OlapTable; +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.Table; +import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.nereids.OptimizerContext; import org.apache.doris.nereids.PlannerContext; @@ -33,9 +35,14 @@ import org.apache.doris.nereids.properties.PhysicalProperties; import org.apache.doris.nereids.rules.Rule; import org.apache.doris.nereids.rules.RuleType; import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.expressions.SlotReference; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.Plans; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.StringType; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -47,7 +54,10 @@ public class RewriteTopDownJobTest implements Plans { @Override public Rule build() { return unboundRelation().then(unboundRelation -> plan( - new LogicalRelation(new OlapTable(), Lists.newArrayList("test")) + new LogicalRelation(new Table(0, "test", Table.TableType.OLAP, ImmutableList.of( + new Column("id", Type.INT), + new Column("name", Type.STRING) + )), Lists.newArrayList("test")) )).toRule(RuleType.BINDING_UNBOUND_RELATION_RULE); } } @@ -56,24 +66,37 @@ public class RewriteTopDownJobTest implements Plans { public void testSimplestScene() throws AnalysisException { UnboundRelation unboundRelation = new UnboundRelation(Lists.newArrayList("test")); Plan leaf = plan(unboundRelation); - LogicalProject project = new LogicalProject(Lists.newArrayList()); + LogicalProject project = new LogicalProject(ImmutableList.of( + new SlotReference("name", StringType.INSTANCE, true, ImmutableList.of("test"))) + ); Plan root = plan(project, leaf); - Memo memo = new Memo(); + Memo memo = new Memo(); memo.initialize(root); - OptimizerContext optimizerContext = new OptimizerContext<>(memo); + OptimizerContext optimizerContext = new OptimizerContext(memo); PlannerContext plannerContext = new PlannerContext(optimizerContext, null, new PhysicalProperties()); List> fakeRules = Lists.newArrayList(new FakeRule().build()); - RewriteTopDownJob rewriteTopDownJob = new RewriteTopDownJob<>(memo.getRoot(), fakeRules, plannerContext); + RewriteTopDownJob rewriteTopDownJob = new RewriteTopDownJob(memo.getRoot(), fakeRules, plannerContext); plannerContext.getOptimizerContext().pushJob(rewriteTopDownJob); plannerContext.getOptimizerContext().getJobScheduler().executeJobPool(plannerContext); Group rootGroup = memo.getRoot(); Assertions.assertEquals(1, rootGroup.getLogicalExpressions().size()); GroupExpression rootGroupExpression = rootGroup.getLogicalExpression(); + List output = rootGroup.getLogicalProperties().getOutput(); + Assertions.assertEquals(output.size(), 1); + Assertions.assertEquals(output.get(0).getName(), "name"); + Assertions.assertEquals(output.get(0).getDataType(), StringType.INSTANCE); Assertions.assertEquals(1, rootGroupExpression.children().size()); Assertions.assertEquals(OperatorType.LOGICAL_PROJECT, rootGroupExpression.getOperator().getType()); + Group leafGroup = rootGroupExpression.child(0); + output = leafGroup.getLogicalProperties().getOutput(); + Assertions.assertEquals(output.size(), 2); + Assertions.assertEquals(output.get(0).getName(), "id"); + Assertions.assertEquals(output.get(0).getDataType(), IntegerType.INSTANCE); + Assertions.assertEquals(output.get(1).getName(), "name"); + Assertions.assertEquals(output.get(1).getDataType(), StringType.INSTANCE); Assertions.assertEquals(1, leafGroup.getLogicalExpressions().size()); GroupExpression leafGroupExpression = leafGroup.getLogicalExpression(); Assertions.assertEquals(OperatorType.LOGICAL_BOUND_RELATION, leafGroupExpression.getOperator().getType()); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/pattern/GroupExpressionMatchingTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/pattern/GroupExpressionMatchingTest.java index 4a3bbed0c4..1231a05a82 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/pattern/GroupExpressionMatchingTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/pattern/GroupExpressionMatchingTest.java @@ -38,10 +38,10 @@ public class GroupExpressionMatchingTest implements Plans { UnboundRelation unboundRelation = new UnboundRelation(Lists.newArrayList("test")); Plan plan = plan(unboundRelation); - Memo memo = new Memo<>(); + Memo memo = new Memo(); memo.initialize(plan); - GroupExpressionMatching groupExpressionMatching + GroupExpressionMatching groupExpressionMatching = new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression()); Iterator iterator = groupExpressionMatching.iterator(); @@ -60,15 +60,15 @@ public class GroupExpressionMatchingTest implements Plans { Plan leaf = plan(unboundRelation); LogicalProject project = new LogicalProject(Lists.newArrayList()); Plan root = plan(project, leaf); - Memo memo = new Memo(); + Memo memo = new Memo(); memo.initialize(root); UnboundRelation anotherUnboundRelation = new UnboundRelation(Lists.newArrayList("test2")); Plan anotherLeaf = plan(anotherUnboundRelation); memo.copyIn(anotherLeaf, memo.getRoot().getLogicalExpression().child(0), false); - GroupExpressionMatching groupExpressionMatching - = new GroupExpressionMatching<>(pattern, memo.getRoot().getLogicalExpression()); + GroupExpressionMatching groupExpressionMatching + = new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression()); Iterator iterator = groupExpressionMatching.iterator(); Assertions.assertTrue(iterator.hasNext()); @@ -93,15 +93,15 @@ public class GroupExpressionMatchingTest implements Plans { Plan leaf = plan(unboundRelation); LogicalProject project = new LogicalProject(Lists.newArrayList()); Plan root = plan(project, leaf); - Memo memo = new Memo(); + Memo memo = new Memo(); memo.initialize(root); UnboundRelation anotherUnboundRelation = new UnboundRelation(Lists.newArrayList("test2")); Plan anotherLeaf = plan(anotherUnboundRelation); memo.copyIn(anotherLeaf, memo.getRoot().getLogicalExpression().child(0), false); - GroupExpressionMatching groupExpressionMatching - = new GroupExpressionMatching<>(pattern, memo.getRoot().getLogicalExpression()); + GroupExpressionMatching groupExpressionMatching + = new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression()); Iterator iterator = groupExpressionMatching.iterator(); Assertions.assertTrue(iterator.hasNext()); 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 new file mode 100644 index 0000000000..e79d55e6da --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/plan/TestPlanOutput.java @@ -0,0 +1,102 @@ +// 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.plan; + +import org.apache.doris.catalog.AggregateType; +import org.apache.doris.catalog.Column; +import org.apache.doris.catalog.Table; +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.LogicalRelation; +import org.apache.doris.nereids.operators.plans.physical.PhysicalScan; +import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.plans.Plans; +import org.apache.doris.nereids.trees.plans.logical.LogicalLeafPlan; +import org.apache.doris.nereids.types.IntegerType; +import org.apache.doris.nereids.types.StringType; + +import com.google.common.collect.ImmutableList; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; + +import java.util.List; + +public class TestPlanOutput implements Plans { + @Test + public void testComputeOutput() { + Table table = new Table(0L, "a", Table.TableType.OLAP, ImmutableList.of( + new Column("id", Type.INT, true, AggregateType.NONE, "0", ""), + new Column("name", Type.STRING, true, AggregateType.NONE, "", "") + )); + LogicalLeafPlan relationPlan = plan( + new LogicalRelation(table, ImmutableList.of("a")) + ); + List output = relationPlan.getOutput(); + Assertions.assertTrue(output.size() == 2); + Assertions.assertEquals(output.get(0).getName(), "id"); + Assertions.assertEquals(output.get(0).getQualifiedName(), "a.id"); + Assertions.assertEquals(output.get(0).getDataType(), IntegerType.INSTANCE); + + Assertions.assertEquals(output.get(1).getName(), "name"); + Assertions.assertEquals(output.get(1).getQualifiedName(), "a.name"); + Assertions.assertEquals(output.get(1).getDataType(), StringType.INSTANCE); + } + + @Test + public void testLazyComputeOutput() { + // not throw exception when create new UnboundRelation + LogicalLeafPlan relationPlan = plan( + new UnboundRelation(ImmutableList.of("a")) + ); + + try { + // throw exception when getOutput + relationPlan.getOutput(); + throw new IllegalStateException("Expect an UnboundException but no exception"); + } catch (UnboundException e) { + // correct exception + } + } + + @Test + public void testWithOutput() { + Table table = new Table(0L, "a", Table.TableType.OLAP, ImmutableList.of( + new Column("id", Type.INT, true, AggregateType.NONE, "0", ""), + new Column("name", Type.STRING, true, AggregateType.NONE, "", "") + )); + LogicalLeafPlan relationPlan = plan( + new LogicalRelation(table, ImmutableList.of("a")) + ); + + List output = relationPlan.getOutput(); + // column prune + LogicalLeafPlan newPlan = relationPlan.withOutput(ImmutableList.of(output.get(0))); + output = newPlan.getOutput(); + Assertions.assertTrue(output.size() == 1); + Assertions.assertEquals(output.get(0).getName(), "id"); + Assertions.assertEquals(output.get(0).getQualifiedName(), "a.id"); + Assertions.assertEquals(output.get(0).getDataType(), IntegerType.INSTANCE); + } + + @Test(expected = NullPointerException.class) + public void testPhysicalPlanMustHaveLogicalProperties() { + plan(new PhysicalScan(OperatorType.PHYSICAL_OLAP_SCAN, ImmutableList.of("tbl")) {}, null); + } +}