[Enhancement](Nereids) Automatic compute logical properties (#10176)
Automatic compute logical properties
This commit is contained in:
@ -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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
private final Memo<NODE_TYPE> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
*
|
||||
* @param memo {@link Memo} reference
|
||||
*/
|
||||
public OptimizerContext(Memo<NODE_TYPE> memo) {
|
||||
public OptimizerContext(Memo memo) {
|
||||
this.memo = memo;
|
||||
this.ruleSet = new RuleSet();
|
||||
this.jobPool = new JobStack();
|
||||
@ -63,7 +62,7 @@ public class OptimizerContext<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
this.ruleSet = ruleSet;
|
||||
}
|
||||
|
||||
public Memo<NODE_TYPE> getMemo() {
|
||||
public Memo getMemo() {
|
||||
return memo;
|
||||
}
|
||||
|
||||
|
||||
@ -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<Plan> memo = new Memo<>();
|
||||
Memo memo = new Memo();
|
||||
memo.initialize(plan);
|
||||
|
||||
OptimizerContext<Plan> optimizerContext = new OptimizerContext<>(memo);
|
||||
OptimizerContext optimizerContext = new OptimizerContext(memo);
|
||||
plannerContext = new PlannerContext(optimizerContext, connectContext, outputProperties);
|
||||
|
||||
plannerContext.getOptimizerContext().pushJob(
|
||||
|
||||
@ -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 {
|
||||
}
|
||||
@ -31,7 +31,7 @@ import java.util.List;
|
||||
*/
|
||||
public class UnboundAlias<CHILD_TYPE extends Expression>
|
||||
extends NamedExpression
|
||||
implements UnaryExpression<CHILD_TYPE> {
|
||||
implements UnaryExpression<CHILD_TYPE>, Unbound {
|
||||
|
||||
public UnboundAlias(CHILD_TYPE child) {
|
||||
super(NodeType.UNBOUND_ALIAS, child);
|
||||
|
||||
@ -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<String> nameParts;
|
||||
|
||||
public UnboundRelation(List<String> nameParts) {
|
||||
@ -64,9 +67,13 @@ public class UnboundRelation extends LogicalLeafOperator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> doComputeOutput() {
|
||||
// fixme: throw unchecked exception
|
||||
throw new IllegalStateException(new UnboundException("output"));
|
||||
public LogicalProperties computeLogicalProperties(Plan... inputs) {
|
||||
return new UnboundLogicalProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> computeOutput() {
|
||||
throw new UnboundException("output");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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<String> nameParts;
|
||||
|
||||
public UnboundSlot(List<String> nameParts) {
|
||||
|
||||
@ -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<String> target;
|
||||
|
||||
public UnboundStar(List<String> target) {
|
||||
|
||||
@ -57,7 +57,7 @@ public class ApplyRuleJob extends Job<Plan> {
|
||||
return;
|
||||
}
|
||||
|
||||
GroupExpressionMatching<Plan> groupExpressionMatching
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(rule.getPattern(), groupExpression);
|
||||
for (Plan plan : groupExpressionMatching) {
|
||||
List<Plan> newPlans = rule.transform(plan, context);
|
||||
|
||||
@ -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<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Job<NODE_TYPE> {
|
||||
public class RewriteBottomUpJob extends Job<Plan> {
|
||||
private final Group group;
|
||||
private final List<Rule<NODE_TYPE>> rules;
|
||||
private final List<Rule<Plan>> rules;
|
||||
private final boolean childrenOptimized;
|
||||
|
||||
public RewriteBottomUpJob(Group group, List<Rule<NODE_TYPE>> rules, PlannerContext context) {
|
||||
public RewriteBottomUpJob(Group group, List<Rule<Plan>> rules, PlannerContext context) {
|
||||
this(group, rules, context, false);
|
||||
}
|
||||
|
||||
private RewriteBottomUpJob(Group group, List<Rule<NODE_TYPE>> rules,
|
||||
private RewriteBottomUpJob(Group group, List<Rule<Plan>> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> 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<Rule<NODE_TYPE>> validRules = getValidRules(logicalExpression, rules);
|
||||
for (Rule<NODE_TYPE> rule : validRules) {
|
||||
GroupExpressionMatching<NODE_TYPE> groupExpressionMatching
|
||||
= new GroupExpressionMatching<>(rule.getPattern(), logicalExpression);
|
||||
for (NODE_TYPE before : groupExpressionMatching) {
|
||||
List<NODE_TYPE> afters = rule.transform(before, context);
|
||||
List<Rule<Plan>> validRules = getValidRules(logicalExpression, rules);
|
||||
for (Rule<Plan> rule : validRules) {
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(rule.getPattern(), logicalExpression);
|
||||
for (Plan before : groupExpressionMatching) {
|
||||
List<Plan> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Job<NODE_TYPE> {
|
||||
public class RewriteTopDownJob extends Job<Plan> {
|
||||
private final Group group;
|
||||
private final List<Rule<NODE_TYPE>> rules;
|
||||
private final List<Rule<Plan>> rules;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -45,7 +45,7 @@ public class RewriteTopDownJob<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Jo
|
||||
* @param rules rewrite rules
|
||||
* @param context planner context
|
||||
*/
|
||||
public RewriteTopDownJob(Group group, List<Rule<NODE_TYPE>> rules, PlannerContext context) {
|
||||
public RewriteTopDownJob(Group group, List<Rule<Plan>> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Jo
|
||||
public void execute() {
|
||||
GroupExpression logicalExpression = group.getLogicalExpression();
|
||||
|
||||
List<Rule<NODE_TYPE>> validRules = getValidRules(logicalExpression, rules);
|
||||
for (Rule<NODE_TYPE> rule : validRules) {
|
||||
GroupExpressionMatching<NODE_TYPE> groupExpressionMatching
|
||||
= new GroupExpressionMatching<>(rule.getPattern(), logicalExpression);
|
||||
for (NODE_TYPE before : groupExpressionMatching) {
|
||||
List<NODE_TYPE> afters = rule.transform(before, context);
|
||||
List<Rule<Plan>> validRules = getValidRules(logicalExpression, rules);
|
||||
for (Rule<Plan> rule : validRules) {
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(rule.getPattern(), logicalExpression);
|
||||
for (Plan before : groupExpressionMatching) {
|
||||
List<Plan> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> extends Jo
|
||||
}
|
||||
|
||||
for (Group childGroup : logicalExpression.children()) {
|
||||
pushTask(new RewriteTopDownJob<>(childGroup, rules, context));
|
||||
pushTask(new RewriteTopDownJob(childGroup, rules, context));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 <NODE_TYPE> should be {@link Plan} or {@link Expression}
|
||||
*/
|
||||
public class Memo<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
public class Memo {
|
||||
private final List<Group> groups = Lists.newArrayList();
|
||||
// we could not use Set, because Set has no get method.
|
||||
private final Map<GroupExpression, GroupExpression> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
* @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<Group> 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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
}
|
||||
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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
* @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<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ public enum OperatorType {
|
||||
LOGICAL_PROJECT,
|
||||
LOGICAL_FILTER,
|
||||
LOGICAL_JOIN,
|
||||
PLACE_HOLDER,
|
||||
|
||||
// physical plan
|
||||
PHYSICAL_OLAP_SCAN,
|
||||
|
||||
@ -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<Slot> 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<Slot> doComputeOutput(Plan left, Plan right);
|
||||
public abstract List<Slot> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ public class LogicalFilter extends LogicalUnaryOperator {
|
||||
|
||||
|
||||
@Override
|
||||
public List<Slot> doComputeOutput(Plan input) {
|
||||
public List<Slot> computeOutput(Plan input) {
|
||||
return input.getOutput();
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ public class LogicalJoin extends LogicalBinaryOperator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> doComputeOutput(Plan leftInput, Plan rightInput) {
|
||||
public List<Slot> computeOutput(Plan leftInput, Plan rightInput) {
|
||||
switch (joinType) {
|
||||
case LEFT_SEMI_JOIN:
|
||||
return ImmutableList.copyOf(leftInput.getOutput());
|
||||
|
||||
@ -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<Slot> computeOutput(Plan... inputs) {
|
||||
return doComputeOutput();
|
||||
public LogicalProperties computeLogicalProperties(Plan... inputs) {
|
||||
Preconditions.checkArgument(inputs.length == 0);
|
||||
return new LogicalProperties(computeOutput());
|
||||
}
|
||||
|
||||
public abstract List<Slot> doComputeOutput();
|
||||
public abstract List<Slot> 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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Slot> computeOutput(Plan... inputs);
|
||||
LogicalProperties computeLogicalProperties(Plan... inputs);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ public class LogicalProject extends LogicalUnaryOperator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> doComputeOutput(Plan input) {
|
||||
public List<Slot> computeOutput(Plan input) {
|
||||
// fixme: not throw a checked exception
|
||||
return projects.stream()
|
||||
.map(namedExpr -> {
|
||||
|
||||
@ -62,7 +62,7 @@ public class LogicalRelation extends LogicalLeafOperator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> doComputeOutput() {
|
||||
public List<Slot> computeOutput() {
|
||||
return table.getBaseSchema()
|
||||
.stream()
|
||||
.map(col -> SlotReference.fromColumn(col, qualifier))
|
||||
|
||||
@ -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<Slot> 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<Slot> doComputeOutput(Plan input);
|
||||
public abstract List<Slot> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs) {
|
||||
return doComputeOutput(logicalProperties, inputs[0], inputs[1]);
|
||||
}
|
||||
|
||||
public List<Slot> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs) {
|
||||
return doComputeOutput(logicalProperties);
|
||||
}
|
||||
|
||||
public List<Slot> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs);
|
||||
|
||||
}
|
||||
|
||||
@ -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<Slot> computeOutputs(LogicalProperties logicalProperties, Plan... inputs) {
|
||||
return doComputeOutput(logicalProperties, inputs[0]);
|
||||
}
|
||||
|
||||
public List<Slot> 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +229,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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<NODE_TYPE extends TreeNode<NODE_TYPE>> implements Iterable<NODE_TYPE> {
|
||||
private final Pattern<? extends NODE_TYPE, NODE_TYPE> pattern;
|
||||
public class GroupExpressionMatching implements Iterable<Plan> {
|
||||
private final Pattern<? extends Plan, Plan> pattern;
|
||||
private final GroupExpression groupExpression;
|
||||
|
||||
public GroupExpressionMatching(Pattern<? extends NODE_TYPE, NODE_TYPE> pattern, GroupExpression groupExpression) {
|
||||
public GroupExpressionMatching(Pattern<? extends Plan, Plan> pattern, GroupExpression groupExpression) {
|
||||
this.pattern = Objects.requireNonNull(pattern);
|
||||
this.groupExpression = Objects.requireNonNull(groupExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupExpressionIterator<NODE_TYPE> iterator() {
|
||||
public GroupExpressionIterator<Plan> iterator() {
|
||||
return new GroupExpressionIterator<>(pattern, groupExpression);
|
||||
}
|
||||
|
||||
@ -97,7 +98,7 @@ public class GroupExpressionMatching<NODE_TYPE extends TreeNode<NODE_TYPE>> 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) {
|
||||
|
||||
@ -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<NODE_TYPE extends TreeNode> implements Iterable<NODE_
|
||||
* @param pattern pattern to match
|
||||
* @param group group to be matched
|
||||
*/
|
||||
public GroupIterator(Pattern<? extends NODE_TYPE, NODE_TYPE> pattern, Group group) {
|
||||
public GroupIterator(Pattern<? extends Plan, Plan> pattern, Group group) {
|
||||
this.pattern = pattern;
|
||||
this.iterator = Lists.newArrayList();
|
||||
for (GroupExpression groupExpression : group.getLogicalExpressions()) {
|
||||
GroupExpressionMatching.GroupExpressionIterator<NODE_TYPE> groupExpressionIterator =
|
||||
GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator =
|
||||
new GroupExpressionMatching(pattern, groupExpression).iterator();
|
||||
if (groupExpressionIterator.hasNext()) {
|
||||
this.iterator.add(groupExpressionIterator);
|
||||
}
|
||||
}
|
||||
for (GroupExpression groupExpression : group.getPhysicalExpressions()) {
|
||||
GroupExpressionMatching.GroupExpressionIterator<NODE_TYPE> groupExpressionIterator =
|
||||
GroupExpressionMatching.GroupExpressionIterator groupExpressionIterator =
|
||||
new GroupExpressionMatching(pattern, groupExpression).iterator();
|
||||
if (groupExpressionIterator.hasNext()) {
|
||||
this.iterator.add(groupExpressionIterator);
|
||||
|
||||
@ -161,7 +161,8 @@ public class Pattern<TYPE extends NODE_TYPE, NODE_TYPE extends TreeNode<NODE_TYP
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern<? extends NODE_TYPE, NODE_TYPE> newChildren(List<Pattern<? extends NODE_TYPE, NODE_TYPE>> children) {
|
||||
public Pattern<? extends NODE_TYPE, NODE_TYPE> withChildren(
|
||||
List<Pattern<? extends NODE_TYPE, NODE_TYPE>> children) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
|
||||
@ -206,9 +206,9 @@ public class JavaAstBuilder extends JavaParserBaseVisitor<JavaAstNode> {
|
||||
} 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());
|
||||
|
||||
@ -36,4 +36,8 @@ public class LogicalProperties {
|
||||
public List<Slot> getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public LogicalProperties withOutput(List<Slot> output) {
|
||||
return new LogicalProperties(output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Slot> getOutput() {
|
||||
throw new UnboundException("output");
|
||||
}
|
||||
}
|
||||
@ -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<NODE_TYPE extends TreeNode<NODE_TYPE>>
|
||||
|
||||
|
||||
public AbstractTreeNode(NodeType type, NODE_TYPE... children) {
|
||||
this(type, null, children);
|
||||
this(type, Optional.empty(), children);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,10 +54,10 @@ public abstract class AbstractTreeNode<NODE_TYPE extends TreeNode<NODE_TYPE>>
|
||||
* @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> 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
|
||||
|
||||
@ -44,5 +44,5 @@ public interface TreeNode<NODE_TYPE extends TreeNode<NODE_TYPE>> {
|
||||
|
||||
int arity();
|
||||
|
||||
NODE_TYPE newChildren(List<NODE_TYPE> children);
|
||||
NODE_TYPE withChildren(List<NODE_TYPE> children);
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ public class EqualTo<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE extend
|
||||
}
|
||||
|
||||
@Override
|
||||
public EqualTo<Expression, Expression> newChildren(List<Expression> children) {
|
||||
public EqualTo<Expression, Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new EqualTo<>(children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ public abstract class Expression extends AbstractTreeNode<Expression> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression newChildren(List<Expression> children) {
|
||||
public Expression withChildren(List<Expression> children) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ public class GreaterThan<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE ex
|
||||
}
|
||||
|
||||
@Override
|
||||
public GreaterThan<Expression, Expression> newChildren(List<Expression> children) {
|
||||
public GreaterThan<Expression, Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new GreaterThan<>(children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class GreaterThanEqual<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TY
|
||||
}
|
||||
|
||||
@Override
|
||||
public GreaterThanEqual<Expression, Expression> newChildren(List<Expression> children) {
|
||||
public GreaterThanEqual<Expression, Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new GreaterThanEqual<>(children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class LessThan<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE exten
|
||||
}
|
||||
|
||||
@Override
|
||||
public LessThan<Expression, Expression> newChildren(List<Expression> children) {
|
||||
public LessThan<Expression, Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new LessThan<>(children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class LessThanEqual<LEFT_CHILD_TYPE extends Expression, RIGHT_CHILD_TYPE
|
||||
}
|
||||
|
||||
@Override
|
||||
public LessThanEqual<Expression, Expression> newChildren(List<Expression> children) {
|
||||
public LessThanEqual<Expression, Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new LessThanEqual<>(children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ public class Not<CHILD_TYPE extends Expression> extends Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Not<Expression> newChildren(List<Expression> children) {
|
||||
public Not<Expression> withChildren(List<Expression> children) {
|
||||
Preconditions.checkArgument(children.size() == 1);
|
||||
return new Not<>(children.get(0));
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends PlanOperator>
|
||||
|
||||
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> 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
|
||||
|
||||
@ -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<PlaceHolderPlan.PlaceHolderOperator> {
|
||||
/** 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<Slot> 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<GroupExpression> getGroupExpression() {
|
||||
@ -44,37 +72,13 @@ public class PlaceHolderPlan implements LeafPlan {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan newChildren(List children) {
|
||||
public PlaceHolderPlan withOutput(List<Slot> output) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafPlanOperator getOperator() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalProperties getLogicalProperties() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Slot> getOutput() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String treeString() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Plan> children() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan child(int index) {
|
||||
throw new RuntimeException();
|
||||
public PlaceHolderPlan withChildren(List<Plan> children) {
|
||||
Preconditions.checkArgument(children.size() == 0);
|
||||
return new PlaceHolderPlan(logicalProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,4 +37,5 @@ public interface Plan extends TreeNode<Plan> {
|
||||
|
||||
String treeString();
|
||||
|
||||
Plan withOutput(List<Slot> output);
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends LogicalOperator>
|
||||
extends AbstractPlan<OP_TYPE> 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> logicalProperties, Plan... children) {
|
||||
super(type, operator, logicalProperties.orElseGet(() -> operator.computeLogicalProperties(children)), children);
|
||||
}
|
||||
|
||||
public AbstractLogicalPlan(NodeType type, OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
Optional<LogicalProperties> logicalProperties, Plan... children) {
|
||||
super(type, operator, groupExpression,
|
||||
logicalProperties.orElseGet(() -> operator.computeLogicalProperties(children)), children);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
|
||||
|
||||
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> logicalProperties,
|
||||
LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(NodeType.LOGICAL, operator, logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
public LogicalBinaryPlan(OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
Optional<LogicalProperties> logicalProperties, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(NodeType.LOGICAL, operator, groupExpression, logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalBinaryPlan<OP_TYPE, Plan, Plan> newChildren(List<Plan> children) {
|
||||
public LogicalBinaryPlan<OP_TYPE, Plan, Plan> withChildren(List<Plan> 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<OP_TYPE, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> withOutput(List<Slot> output) {
|
||||
return new LogicalBinaryPlan<>(operator, groupExpression,
|
||||
Optional.of(logicalProperties.withOutput(output)), left(), right());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends LogicalLeafOperator>
|
||||
super(NodeType.LOGICAL, operator);
|
||||
}
|
||||
|
||||
public LogicalLeafPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties) {
|
||||
public LogicalLeafPlan(OP_TYPE operator, Optional<LogicalProperties> logicalProperties) {
|
||||
super(NodeType.LOGICAL, operator, logicalProperties);
|
||||
}
|
||||
|
||||
public LogicalLeafPlan(OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
Optional<LogicalProperties> logicalProperties) {
|
||||
super(NodeType.LOGICAL, operator, groupExpression, logicalProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalLeafPlan<OP_TYPE> newChildren(List<Plan> children) {
|
||||
public LogicalLeafPlan<OP_TYPE> withChildren(List<Plan> children) {
|
||||
Preconditions.checkArgument(children.size() == 0);
|
||||
return new LogicalLeafPlan(operator, groupExpression.orElse(null), logicalProperties);
|
||||
return new LogicalLeafPlan(operator, groupExpression, Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalLeafPlan<OP_TYPE> withOutput(List<Slot> output) {
|
||||
return new LogicalLeafPlan<>(operator, groupExpression,
|
||||
Optional.of(logicalProperties.withOutput(output)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public interface LogicalPlan extends Plan {
|
||||
LogicalOperator getOperator();
|
||||
|
||||
@Override
|
||||
LogicalPlan newChildren(List<Plan> children);
|
||||
LogicalPlan withChildren(List<Plan> children);
|
||||
|
||||
/**
|
||||
* Map a [[LogicalPlan]] to another [[LogicalPlan]] if the passed context exists using the
|
||||
|
||||
@ -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<OP_TYPE extends LogicalUnaryOperator, CHILD_TYPE e
|
||||
super(NodeType.LOGICAL, operator, child);
|
||||
}
|
||||
|
||||
public LogicalUnaryPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties,
|
||||
CHILD_TYPE child) {
|
||||
public LogicalUnaryPlan(OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
Optional<LogicalProperties> logicalProperties, CHILD_TYPE child) {
|
||||
super(NodeType.LOGICAL, operator, groupExpression, logicalProperties, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalUnaryPlan<OP_TYPE, Plan> newChildren(List<Plan> children) {
|
||||
public LogicalUnaryPlan<OP_TYPE, Plan> withChildren(List<Plan> 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<OP_TYPE, CHILD_TYPE> withOutput(List<Slot> output) {
|
||||
return new LogicalUnaryPlan<>(operator, groupExpression,
|
||||
Optional.of(logicalProperties.withOutput(output)), child());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends PhysicalOperator>
|
||||
extends AbstractPlan<OP_TYPE>
|
||||
implements PhysicalPlan {
|
||||
|
||||
protected final LogicalProperties logicalProperties;
|
||||
protected final PhysicalProperties physicalProperties;
|
||||
|
||||
/**
|
||||
@ -44,8 +43,7 @@ public abstract class AbstractPhysicalPlan<OP_TYPE extends PhysicalOperator>
|
||||
*/
|
||||
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<OP_TYPE extends PhysicalOperator>
|
||||
* @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> 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();
|
||||
}
|
||||
|
||||
@ -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> groupExpression,
|
||||
LogicalProperties logicalProperties, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalBinaryPlan<OP_TYPE, Plan, Plan> newChildren(List<Plan> children) {
|
||||
public PhysicalBinaryPlan<OP_TYPE, Plan, Plan> withChildren(List<Plan> 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<OP_TYPE, LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> withOutput(List<Slot> output) {
|
||||
LogicalProperties logicalProperties = new LogicalProperties(output);
|
||||
return new PhysicalBinaryPlan<>(operator, groupExpression, logicalProperties, left(), right());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends PhysicalLeafOperator>
|
||||
super(NodeType.PHYSICAL, operator, logicalProperties);
|
||||
}
|
||||
|
||||
public PhysicalLeafPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties) {
|
||||
public PhysicalLeafPlan(OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
LogicalProperties logicalProperties) {
|
||||
super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalLeafPlan<OP_TYPE> newChildren(List<Plan> children) {
|
||||
public PhysicalLeafPlan<OP_TYPE> withChildren(List<Plan> children) {
|
||||
Preconditions.checkArgument(children.size() == 0);
|
||||
return new PhysicalLeafPlan(operator, groupExpression.orElse(null), logicalProperties);
|
||||
return new PhysicalLeafPlan(operator, groupExpression, logicalProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalLeafPlan<OP_TYPE> withOutput(List<Slot> output) {
|
||||
LogicalProperties logicalProperties = new LogicalProperties(output);
|
||||
return new PhysicalLeafPlan<>(operator, groupExpression, logicalProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<OP_TYPE extends PhysicalUnaryOperator, CHILD_TYPE
|
||||
super(NodeType.PHYSICAL, operator, logicalProperties, child);
|
||||
}
|
||||
|
||||
public PhysicalUnaryPlan(OP_TYPE operator, GroupExpression groupExpression, LogicalProperties logicalProperties,
|
||||
CHILD_TYPE child) {
|
||||
public PhysicalUnaryPlan(OP_TYPE operator, Optional<GroupExpression> groupExpression,
|
||||
LogicalProperties logicalProperties, CHILD_TYPE child) {
|
||||
super(NodeType.PHYSICAL, operator, groupExpression, logicalProperties, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalUnaryPlan<OP_TYPE, Plan> newChildren(List<Plan> children) {
|
||||
public PhysicalUnaryPlan<OP_TYPE, Plan> withChildren(List<Plan> 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<OP_TYPE, CHILD_TYPE> withOutput(List<Slot> output) {
|
||||
LogicalProperties logicalProperties = new LogicalProperties(output);
|
||||
return new PhysicalUnaryPlan<>(operator, groupExpression, logicalProperties, child());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Plan> 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<Plan> memo = new Memo();
|
||||
Memo memo = new Memo();
|
||||
memo.initialize(root);
|
||||
|
||||
OptimizerContext<Plan> optimizerContext = new OptimizerContext<>(memo);
|
||||
OptimizerContext optimizerContext = new OptimizerContext(memo);
|
||||
PlannerContext plannerContext = new PlannerContext(optimizerContext, null, new PhysicalProperties());
|
||||
List<Rule<Plan>> fakeRules = Lists.newArrayList(new FakeRule().build());
|
||||
RewriteTopDownJob<Plan> 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<Slot> 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());
|
||||
|
||||
@ -38,10 +38,10 @@ public class GroupExpressionMatchingTest implements Plans {
|
||||
|
||||
UnboundRelation unboundRelation = new UnboundRelation(Lists.newArrayList("test"));
|
||||
Plan plan = plan(unboundRelation);
|
||||
Memo<Plan> memo = new Memo<>();
|
||||
Memo memo = new Memo();
|
||||
memo.initialize(plan);
|
||||
|
||||
GroupExpressionMatching<Plan> groupExpressionMatching
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression());
|
||||
Iterator<Plan> 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<Plan> 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<Plan> groupExpressionMatching
|
||||
= new GroupExpressionMatching<>(pattern, memo.getRoot().getLogicalExpression());
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression());
|
||||
Iterator<Plan> 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<Plan> 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<Plan> groupExpressionMatching
|
||||
= new GroupExpressionMatching<>(pattern, memo.getRoot().getLogicalExpression());
|
||||
GroupExpressionMatching groupExpressionMatching
|
||||
= new GroupExpressionMatching(pattern, memo.getRoot().getLogicalExpression());
|
||||
Iterator<Plan> iterator = groupExpressionMatching.iterator();
|
||||
|
||||
Assertions.assertTrue(iterator.hasNext());
|
||||
|
||||
@ -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.<Column>of(
|
||||
new Column("id", Type.INT, true, AggregateType.NONE, "0", ""),
|
||||
new Column("name", Type.STRING, true, AggregateType.NONE, "", "")
|
||||
));
|
||||
LogicalLeafPlan<LogicalRelation> relationPlan = plan(
|
||||
new LogicalRelation(table, ImmutableList.of("a"))
|
||||
);
|
||||
List<Slot> 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<UnboundRelation> 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<LogicalRelation> relationPlan = plan(
|
||||
new LogicalRelation(table, ImmutableList.of("a"))
|
||||
);
|
||||
|
||||
List<Slot> output = relationPlan.getOutput();
|
||||
// column prune
|
||||
LogicalLeafPlan<LogicalRelation> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user