[feature](Nereids) support cross join in Nereids (#11502)
support cross join in Nereids 1. add PhysicalNestedLoopJoin 2. Translate PhysicalNestedLoopJoin to CrossJoinNode in PhysicalPlanTranslator
This commit is contained in:
@ -24,6 +24,7 @@ under the License.
|
||||
|
||||
<import-control pkg="org.apache.doris" strategyOnMismatch="allowed">
|
||||
<disallow pkg="com.clearspring.analytics.util" />
|
||||
<disallow pkg="com.alibaba.google" />
|
||||
<subpackage name="nereids">
|
||||
<allow pkg="org.junit.jupiter"/>
|
||||
<disallow pkg="org.junit"/>
|
||||
|
||||
@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalAggregate;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalDistribution;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHeapSort;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
@ -133,5 +134,32 @@ public class CostCalculator {
|
||||
0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CostEstimate visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin,
|
||||
PlanContext context) {
|
||||
// TODO: copy from physicalHashJoin, should update according to physical nested loop join properties.
|
||||
Preconditions.checkState(context.getGroupExpression().arity() == 2);
|
||||
Preconditions.checkState(context.getChildrenStats().size() == 2);
|
||||
|
||||
StatsDeriveResult leftStatistics = context.getChildStatistics(0);
|
||||
StatsDeriveResult rightStatistics = context.getChildStatistics(1);
|
||||
List<Id> leftIds = context.getChildOutputIds(0);
|
||||
List<Id> rightIds = context.getChildOutputIds(1);
|
||||
|
||||
// TODO: handle some case
|
||||
// handle cross join, onClause is empty .....
|
||||
if (nestedLoopJoin.getJoinType().isCrossJoin()) {
|
||||
return new CostEstimate(
|
||||
leftStatistics.computeColumnSize(leftIds) + rightStatistics.computeColumnSize(rightIds),
|
||||
rightStatistics.computeColumnSize(rightIds),
|
||||
0);
|
||||
}
|
||||
|
||||
// TODO: network 0?
|
||||
return new CostEstimate(
|
||||
(leftStatistics.computeColumnSize(leftIds) + rightStatistics.computeColumnSize(rightIds)) / 2,
|
||||
rightStatistics.computeColumnSize(rightIds),
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,14 +47,17 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHeapSort;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalLimit;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanVisitor;
|
||||
import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
import org.apache.doris.nereids.util.JoinUtils;
|
||||
import org.apache.doris.nereids.util.SlotExtractor;
|
||||
import org.apache.doris.nereids.util.Utils;
|
||||
import org.apache.doris.planner.AggregationNode;
|
||||
import org.apache.doris.planner.CrossJoinNode;
|
||||
import org.apache.doris.planner.DataPartition;
|
||||
import org.apache.doris.planner.ExchangeNode;
|
||||
import org.apache.doris.planner.HashJoinNode;
|
||||
@ -338,8 +341,7 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla
|
||||
PlanNode rightFragmentPlanRoot = rightFragment.getPlanRoot();
|
||||
JoinType joinType = hashJoin.getJoinType();
|
||||
|
||||
if (joinType.equals(JoinType.CROSS_JOIN)
|
||||
|| (joinType.equals(JoinType.INNER_JOIN) && !hashJoin.getCondition().isPresent())) {
|
||||
if (JoinUtils.shouldNestedLoopJoin(hashJoin)) {
|
||||
throw new RuntimeException("Physical hash join could not execute without equal join condition.");
|
||||
} else {
|
||||
Expression eqJoinExpression = hashJoin.getCondition().get();
|
||||
@ -368,6 +370,30 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlanFragment visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin,
|
||||
PlanTranslatorContext context) {
|
||||
// NOTICE: We must visit from right to left, to ensure the last fragment is root fragment
|
||||
// TODO: we should add a helper method to wrap this logic.
|
||||
// Maybe something like private List<PlanFragment> postOrderVisitChildren(
|
||||
// PhysicalPlan plan, PlanVisitor visitor, Context context).
|
||||
PlanFragment rightFragment = nestedLoopJoin.child(1).accept(this, context);
|
||||
PlanFragment leftFragment = nestedLoopJoin.child(0).accept(this, context);
|
||||
PlanNode leftFragmentPlanRoot = leftFragment.getPlanRoot();
|
||||
PlanNode rightFragmentPlanRoot = rightFragment.getPlanRoot();
|
||||
if (JoinUtils.shouldNestedLoopJoin(nestedLoopJoin)) {
|
||||
CrossJoinNode crossJoinNode =
|
||||
new CrossJoinNode(context.nextPlanNodeId(), leftFragmentPlanRoot, rightFragmentPlanRoot, null);
|
||||
rightFragment.getPlanRoot().setCompactData(false);
|
||||
crossJoinNode.setChild(0, leftFragment.getPlanRoot());
|
||||
connectChildFragment(crossJoinNode, 1, leftFragment, rightFragment, context);
|
||||
leftFragment.setPlanRoot(crossJoinNode);
|
||||
return leftFragment;
|
||||
} else {
|
||||
throw new RuntimeException("Physical nested loop join could not execute with equal join condition.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: generate expression mapping when be project could do in ExecNode
|
||||
@Override
|
||||
public PlanFragment visitPhysicalProject(PhysicalProject<Plan> project, PlanTranslatorContext context) {
|
||||
|
||||
@ -48,6 +48,10 @@ public class PatternDescriptor<INPUT_TYPE extends Plan> {
|
||||
return new PatternDescriptor<>(pattern.withPredicates(predicates), defaultPromise);
|
||||
}
|
||||
|
||||
public PatternDescriptor<INPUT_TYPE> whenNot(Predicate<INPUT_TYPE> predicate) {
|
||||
return when(predicate.negate());
|
||||
}
|
||||
|
||||
public <OUTPUT_TYPE extends Plan> PatternMatcher<INPUT_TYPE, OUTPUT_TYPE> then(
|
||||
Function<INPUT_TYPE, OUTPUT_TYPE> matchedAction) {
|
||||
return new PatternMatcher<>(pattern, defaultPromise, ctx -> matchedAction.apply(ctx.root));
|
||||
|
||||
@ -21,6 +21,7 @@ import org.apache.doris.nereids.PlanContext;
|
||||
import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
@ -99,6 +100,40 @@ public class ChildOutputPropertyDeriver extends PlanVisitor<PhysicalProperties,
|
||||
return leftOutputProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalProperties visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin,
|
||||
PlanContext context) {
|
||||
// TODO: copy from hash join, should update according to nested loop join properties.
|
||||
Preconditions.checkState(childrenOutputProperties.size() == 2);
|
||||
PhysicalProperties leftOutputProperty = childrenOutputProperties.get(0);
|
||||
PhysicalProperties rightOutputProperty = childrenOutputProperties.get(1);
|
||||
|
||||
// broadcast
|
||||
if (rightOutputProperty.getDistributionSpec() instanceof DistributionSpecReplicated) {
|
||||
// TODO
|
||||
return leftOutputProperty;
|
||||
}
|
||||
|
||||
// shuffle
|
||||
// List<SlotReference> leftSlotRefs = hashJoin.left().getOutput().stream().map(slot -> (SlotReference) slot)
|
||||
// .collect(Collectors.toList());
|
||||
// List<SlotReference> rightSlotRefs = hashJoin.right().getOutput().stream().map(slot -> (SlotReference) slot)
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
// List<SlotReference> leftOnSlotRefs;
|
||||
// List<SlotReference> rightOnSlotRefs;
|
||||
// Preconditions.checkState(leftOnSlotRefs.size() == rightOnSlotRefs.size());
|
||||
DistributionSpec leftDistribution = leftOutputProperty.getDistributionSpec();
|
||||
DistributionSpec rightDistribution = rightOutputProperty.getDistributionSpec();
|
||||
if (!(leftDistribution instanceof DistributionSpecHash)
|
||||
|| !(rightDistribution instanceof DistributionSpecHash)) {
|
||||
Preconditions.checkState(false, "error");
|
||||
return new PhysicalProperties();
|
||||
}
|
||||
|
||||
return leftOutputProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalProperties visitPhysicalOlapScan(PhysicalOlapScan olapScan, PlanContext context) {
|
||||
return olapScan.getPhysicalProperties();
|
||||
|
||||
@ -25,6 +25,7 @@ import org.apache.doris.nereids.properties.DistributionSpecHash.ShuffleType;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
import org.apache.doris.nereids.util.JoinUtils;
|
||||
import org.apache.doris.nereids.util.Utils;
|
||||
@ -92,6 +93,31 @@ public class RequestPropertyDeriver extends PlanVisitor<Void, PlanContext> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin, PlanContext context) {
|
||||
// TODO: copy from physicalHashJoin, should update according to physical nested loop join properties.
|
||||
// for broadcast join
|
||||
List<PhysicalProperties> propertiesForBroadcast = Lists.newArrayList(
|
||||
new PhysicalProperties(),
|
||||
new PhysicalProperties(new DistributionSpecReplicated())
|
||||
);
|
||||
// for shuffle join
|
||||
Pair<List<SlotReference>, List<SlotReference>> onClauseUsedSlots
|
||||
= JoinUtils.getOnClauseUsedSlots(nestedLoopJoin);
|
||||
List<PhysicalProperties> propertiesForShuffle = Lists.newArrayList(
|
||||
new PhysicalProperties(new DistributionSpecHash(onClauseUsedSlots.first, ShuffleType.JOIN)),
|
||||
new PhysicalProperties(new DistributionSpecHash(onClauseUsedSlots.second, ShuffleType.JOIN)));
|
||||
|
||||
if (!JoinUtils.onlyBroadcast(nestedLoopJoin)) {
|
||||
requestPropertyToChildren.add(propertiesForShuffle);
|
||||
}
|
||||
if (!JoinUtils.onlyShuffle(nestedLoopJoin)) {
|
||||
requestPropertyToChildren.add(propertiesForBroadcast);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static List<PhysicalProperties> computeShuffleJoinRequiredProperties(
|
||||
PhysicalProperties requestedProperty, List<SlotReference> leftShuffleColumns,
|
||||
List<SlotReference> rightShuffleColumns) {
|
||||
|
||||
@ -21,6 +21,7 @@ import org.apache.doris.nereids.rules.exploration.join.JoinCommute;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalAggToPhysicalHashAgg;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalFilterToPhysicalFilter;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalJoinToHashJoin;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalJoinToNestedLoopJoin;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalLimitToPhysicalLimit;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalOlapScanToPhysicalOlapScan;
|
||||
import org.apache.doris.nereids.rules.implementation.LogicalProjectToPhysicalProject;
|
||||
@ -48,6 +49,7 @@ public class RuleSet {
|
||||
.add(new LogicalAggToPhysicalHashAgg())
|
||||
.add(new LogicalFilterToPhysicalFilter())
|
||||
.add(new LogicalJoinToHashJoin())
|
||||
.add(new LogicalJoinToNestedLoopJoin())
|
||||
.add(new LogicalOlapScanToPhysicalOlapScan())
|
||||
.add(new LogicalProjectToPhysicalProject())
|
||||
.add(new LogicalLimitToPhysicalLimit())
|
||||
|
||||
@ -68,6 +68,7 @@ public enum RuleType {
|
||||
// implementation rules
|
||||
LOGICAL_AGG_TO_PHYSICAL_HASH_AGG_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
LOGICAL_JOIN_TO_HASH_JOIN_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
LOGICAL_JOIN_TO_NESTED_LOOP_JOIN_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
LOGICAL_PROJECT_TO_PHYSICAL_PROJECT_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
LOGICAL_FILTER_TO_PHYSICAL_FILTER_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
LOGICAL_SORT_TO_PHYSICAL_HEAP_SORT_RULE(RuleTypeClass.IMPLEMENTATION),
|
||||
|
||||
@ -20,6 +20,7 @@ package org.apache.doris.nereids.rules.implementation;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.util.JoinUtils;
|
||||
|
||||
/**
|
||||
* Implementation rule that convert logical join to physical hash join.
|
||||
@ -27,7 +28,9 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
public class LogicalJoinToHashJoin extends OneImplementationRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
return logicalJoin().then(join -> new PhysicalHashJoin<>(
|
||||
return logicalJoin()
|
||||
.whenNot(JoinUtils::shouldNestedLoopJoin)
|
||||
.then(join -> new PhysicalHashJoin<>(
|
||||
join.getJoinType(),
|
||||
join.getCondition(),
|
||||
join.getLogicalProperties(),
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.implementation;
|
||||
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.util.JoinUtils;
|
||||
|
||||
/**
|
||||
* Implementation rule that convert logical join to physical nested loop join.
|
||||
*/
|
||||
public class LogicalJoinToNestedLoopJoin extends OneImplementationRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
return logicalJoin()
|
||||
.when(JoinUtils::shouldNestedLoopJoin)
|
||||
.then(join -> new PhysicalNestedLoopJoin<>(
|
||||
join.getJoinType(),
|
||||
join.getCondition(),
|
||||
join.getLogicalProperties(),
|
||||
join.left(),
|
||||
join.right())
|
||||
).toRule(RuleType.LOGICAL_JOIN_TO_NESTED_LOOP_JOIN_RULE);
|
||||
}
|
||||
}
|
||||
@ -22,14 +22,17 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Join;
|
||||
import org.apache.doris.nereids.util.ExpressionUtils;
|
||||
import org.apache.doris.statistics.ColumnStats;
|
||||
import org.apache.doris.statistics.StatsDeriveResult;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Estimate hash join stats.
|
||||
@ -40,11 +43,13 @@ public class JoinEstimation {
|
||||
/**
|
||||
* Do estimate.
|
||||
*/
|
||||
public static StatsDeriveResult estimate(StatsDeriveResult leftStats, StatsDeriveResult rightStats,
|
||||
Expression eqCondition, JoinType joinType) {
|
||||
public static StatsDeriveResult estimate(StatsDeriveResult leftStats, StatsDeriveResult rightStats, Join join) {
|
||||
Optional<Expression> eqCondition = join.getCondition();
|
||||
JoinType joinType = join.getJoinType();
|
||||
StatsDeriveResult statsDeriveResult = new StatsDeriveResult(leftStats);
|
||||
statsDeriveResult.merge(rightStats);
|
||||
List<Expression> eqConjunctList = ExpressionUtils.extractConjunction(eqCondition);
|
||||
List<Expression> eqConjunctList = Lists.newArrayList();
|
||||
eqCondition.ifPresent(e -> eqConjunctList.addAll(ExpressionUtils.extractConjunction(e)));
|
||||
long rowCount = -1;
|
||||
if (joinType.isSemiOrAntiJoin()) {
|
||||
rowCount = getSemiJoinRowCount(leftStats, rightStats, eqConjunctList, joinType);
|
||||
|
||||
@ -23,12 +23,12 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.Project;
|
||||
import org.apache.doris.nereids.trees.plans.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Project;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
@ -42,6 +42,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHeapSort;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalLimit;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanVisitor;
|
||||
@ -119,8 +120,7 @@ public class StatsCalculator extends DefaultPlanVisitor<StatsDeriveResult, Void>
|
||||
@Override
|
||||
public StatsDeriveResult visitLogicalJoin(LogicalJoin<Plan, Plan> join, Void context) {
|
||||
return JoinEstimation.estimate(groupExpression.getCopyOfChildStats(0),
|
||||
groupExpression.getCopyOfChildStats(1),
|
||||
join.getCondition().get(), join.getJoinType());
|
||||
groupExpression.getCopyOfChildStats(1), join);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -141,8 +141,14 @@ public class StatsCalculator extends DefaultPlanVisitor<StatsDeriveResult, Void>
|
||||
@Override
|
||||
public StatsDeriveResult visitPhysicalHashJoin(PhysicalHashJoin<Plan, Plan> hashJoin, Void context) {
|
||||
return JoinEstimation.estimate(groupExpression.getCopyOfChildStats(0),
|
||||
groupExpression.getCopyOfChildStats(1),
|
||||
hashJoin.getCondition().get(), hashJoin.getJoinType());
|
||||
groupExpression.getCopyOfChildStats(1), hashJoin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatsDeriveResult visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin,
|
||||
Void context) {
|
||||
return JoinEstimation.estimate(groupExpression.getCopyOfChildStats(0),
|
||||
groupExpression.getCopyOfChildStats(1), nestedLoopJoin);
|
||||
}
|
||||
|
||||
// TODO: We should subtract those pruned column, and consider the expression transformations in the node.
|
||||
|
||||
@ -17,7 +17,8 @@
|
||||
|
||||
package org.apache.doris.nereids.trees;
|
||||
|
||||
import com.alibaba.google.common.collect.ImmutableList;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -47,6 +47,7 @@ public enum PlanType {
|
||||
PHYSICAL_SORT,
|
||||
PHYSICAL_LIMIT,
|
||||
PHYSICAL_HASH_JOIN,
|
||||
PHYSICAL_NESTED_LOOP_JOIN,
|
||||
PHYSICAL_EXCHANGE,
|
||||
PHYSICAL_DISTRIBUTION;
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.plans;
|
||||
package org.apache.doris.nereids.trees.plans.algebra;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.plans;
|
||||
package org.apache.doris.nereids.trees.plans.algebra;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// 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.trees.plans.algebra;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Common interface for logical/physical join.
|
||||
*/
|
||||
public interface Join {
|
||||
JoinType getJoinType();
|
||||
|
||||
Optional<Expression> getCondition();
|
||||
}
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.plans;
|
||||
package org.apache.doris.nereids.trees.plans.algebra;
|
||||
|
||||
/**
|
||||
* Common interface for logical/physical limit.
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.plans;
|
||||
package org.apache.doris.nereids.trees.plans.algebra;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.trees.plans;
|
||||
package org.apache.doris.nereids.trees.plans.algebra;
|
||||
|
||||
import org.apache.doris.catalog.Table;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
@ -23,9 +23,9 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.AggPhase;
|
||||
import org.apache.doris.nereids.trees.plans.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -21,9 +21,9 @@ import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -25,6 +25,7 @@ import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Join;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
@ -39,7 +40,7 @@ import java.util.stream.Collectors;
|
||||
* Logical join plan.
|
||||
*/
|
||||
public class LogicalJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends Plan>
|
||||
extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
|
||||
extends LogicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements Join {
|
||||
|
||||
private final JoinType joinType;
|
||||
private final Optional<Expression> condition;
|
||||
|
||||
@ -22,9 +22,9 @@ import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.IntegerLiteral;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -24,7 +24,7 @@ import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.Project;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Project;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -24,7 +24,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
import org.apache.doris.nereids.util.Utils;
|
||||
|
||||
|
||||
@ -22,9 +22,9 @@ import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.plans.AggPhase;
|
||||
import org.apache.doris.nereids.trees.plans.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Aggregate;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -20,9 +20,9 @@ package org.apache.doris.nereids.trees.plans.physical;
|
||||
import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Filter;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -26,10 +26,8 @@ import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -38,12 +36,7 @@ import java.util.Optional;
|
||||
public class PhysicalHashJoin<
|
||||
LEFT_CHILD_TYPE extends Plan,
|
||||
RIGHT_CHILD_TYPE extends Plan>
|
||||
extends PhysicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
|
||||
|
||||
private final JoinType joinType;
|
||||
|
||||
private final Optional<Expression> condition;
|
||||
|
||||
extends PhysicalJoin<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
|
||||
|
||||
public PhysicalHashJoin(JoinType joinType, Optional<Expression> condition, LogicalProperties logicalProperties,
|
||||
LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
@ -59,17 +52,8 @@ public class PhysicalHashJoin<
|
||||
public PhysicalHashJoin(JoinType joinType, Optional<Expression> condition,
|
||||
Optional<GroupExpression> groupExpression, LogicalProperties logicalProperties,
|
||||
LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(PlanType.PHYSICAL_HASH_JOIN, groupExpression, logicalProperties, leftChild, rightChild);
|
||||
this.joinType = Objects.requireNonNull(joinType, "joinType can not be null");
|
||||
this.condition = Objects.requireNonNull(condition, "condition can not be null");
|
||||
}
|
||||
|
||||
public JoinType getJoinType() {
|
||||
return joinType;
|
||||
}
|
||||
|
||||
public Optional<Expression> getCondition() {
|
||||
return condition;
|
||||
super(PlanType.PHYSICAL_HASH_JOIN, joinType, condition,
|
||||
groupExpression, logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,11 +61,6 @@ public class PhysicalHashJoin<
|
||||
return visitor.visitPhysicalHashJoin((PhysicalHashJoin<Plan, Plan>) this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression> getExpressions() {
|
||||
return condition.<List<Expression>>map(ImmutableList::of).orElseGet(ImmutableList::of);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@ -93,23 +72,6 @@ public class PhysicalHashJoin<
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PhysicalHashJoin that = (PhysicalHashJoin) o;
|
||||
return joinType == that.joinType && Objects.equals(condition, that.condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(joinType, condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalBinary<Plan, Plan> withChildren(List<Plan> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
// 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.trees.plans.physical;
|
||||
|
||||
import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Join;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Abstract class for all physical join node.
|
||||
*/
|
||||
public abstract class PhysicalJoin<
|
||||
LEFT_CHILD_TYPE extends Plan,
|
||||
RIGHT_CHILD_TYPE extends Plan>
|
||||
extends PhysicalBinary<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> implements Join {
|
||||
protected final JoinType joinType;
|
||||
|
||||
protected final Optional<Expression> condition;
|
||||
|
||||
/**
|
||||
* Constructor of PhysicalJoin.
|
||||
*
|
||||
* @param joinType Which join type, left semi join, inner join...
|
||||
* @param condition join condition.
|
||||
*/
|
||||
public PhysicalJoin(PlanType type, JoinType joinType, Optional<Expression> condition,
|
||||
Optional<GroupExpression> groupExpression, LogicalProperties logicalProperties,
|
||||
LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(type, groupExpression, logicalProperties, leftChild, rightChild);
|
||||
this.joinType = Objects.requireNonNull(joinType, "joinType can not be null");
|
||||
this.condition = Objects.requireNonNull(condition, "condition can not be null");
|
||||
}
|
||||
|
||||
public JoinType getJoinType() {
|
||||
return joinType;
|
||||
}
|
||||
|
||||
public Optional<Expression> getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression> getExpressions() {
|
||||
return condition.<List<Expression>>map(ImmutableList::of).orElseGet(ImmutableList::of);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PhysicalJoin that = (PhysicalJoin) o;
|
||||
return joinType == that.joinType && Objects.equals(condition, that.condition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(joinType, condition);
|
||||
}
|
||||
}
|
||||
@ -21,9 +21,9 @@ import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.IntegerLiteral;
|
||||
import org.apache.doris.nereids.trees.plans.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Limit;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
// 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.trees.plans.physical;
|
||||
|
||||
import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Use nested loop algorithm to do join.
|
||||
*/
|
||||
public class PhysicalNestedLoopJoin<
|
||||
LEFT_CHILD_TYPE extends Plan,
|
||||
RIGHT_CHILD_TYPE extends Plan>
|
||||
extends PhysicalJoin<LEFT_CHILD_TYPE, RIGHT_CHILD_TYPE> {
|
||||
|
||||
public PhysicalNestedLoopJoin(JoinType joinType, Optional<Expression> condition,
|
||||
LogicalProperties logicalProperties, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
this(joinType, condition, Optional.empty(), logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of PhysicalNestedLoopJoin.
|
||||
*
|
||||
* @param joinType Which join type, left semi join, inner join...
|
||||
* @param condition join condition.
|
||||
*/
|
||||
public PhysicalNestedLoopJoin(JoinType joinType, Optional<Expression> condition,
|
||||
Optional<GroupExpression> groupExpression, LogicalProperties logicalProperties,
|
||||
LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
super(PlanType.PHYSICAL_NESTED_LOOP_JOIN, joinType, condition,
|
||||
groupExpression, logicalProperties, leftChild, rightChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, C> R accept(PlanVisitor<R, C> visitor, C context) {
|
||||
return visitor.visitPhysicalNestedLoopJoin((PhysicalNestedLoopJoin<Plan, Plan>) this, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO: Maybe we could pull up this to the abstract class in the future.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("PhysicalNestedLoopJoin ([").append(joinType).append("]");
|
||||
condition.ifPresent(
|
||||
expression -> sb.append(", [").append(expression).append("]")
|
||||
);
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhysicalBinary<Plan, Plan> withChildren(List<Plan> children) {
|
||||
Preconditions.checkArgument(children.size() == 2);
|
||||
return new PhysicalNestedLoopJoin<>(joinType, condition, logicalProperties, children.get(0), children.get(1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan withGroupExpression(Optional<GroupExpression> groupExpression) {
|
||||
return new PhysicalNestedLoopJoin<>(joinType, condition, groupExpression, logicalProperties, left(), right());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan withLogicalProperties(Optional<LogicalProperties> logicalProperties) {
|
||||
return new PhysicalNestedLoopJoin<>(joinType, condition, Optional.empty(),
|
||||
logicalProperties.get(), left(), right());
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.NamedExpression;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.Project;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Project;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
@ -21,7 +21,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.properties.LogicalProperties;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Scan;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@ -37,6 +37,7 @@ import org.apache.doris.nereids.trees.plans.physical.PhysicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHeapSort;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalLimit;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalNestedLoopJoin;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalRelation;
|
||||
@ -136,6 +137,10 @@ public abstract class PlanVisitor<R, C> {
|
||||
return visit(hashJoin, context);
|
||||
}
|
||||
|
||||
public R visitPhysicalNestedLoopJoin(PhysicalNestedLoopJoin<Plan, Plan> nestedLoopJoin, C context) {
|
||||
return visit(nestedLoopJoin, context);
|
||||
}
|
||||
|
||||
public R visitPhysicalProject(PhysicalProject<Plan> project, C context) {
|
||||
return visit(project, context);
|
||||
}
|
||||
|
||||
@ -21,8 +21,10 @@ import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.trees.expressions.EqualTo;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalHashJoin;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Join;
|
||||
import org.apache.doris.nereids.trees.plans.physical.PhysicalJoin;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
@ -34,19 +36,19 @@ import java.util.List;
|
||||
* Utils for join
|
||||
*/
|
||||
public class JoinUtils {
|
||||
public static boolean onlyBroadcast(PhysicalHashJoin join) {
|
||||
public static boolean onlyBroadcast(PhysicalJoin join) {
|
||||
// Cross-join only can be broadcast join.
|
||||
return join.getJoinType().isCrossJoin();
|
||||
}
|
||||
|
||||
public static boolean onlyShuffle(PhysicalHashJoin join) {
|
||||
public static boolean onlyShuffle(PhysicalJoin join) {
|
||||
return join.getJoinType().isRightJoin() || join.getJoinType().isFullOuterJoin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all equalTo from onClause of join
|
||||
*/
|
||||
public static List<EqualTo> getEqualTo(PhysicalHashJoin<Plan, Plan> join) {
|
||||
public static List<EqualTo> getEqualTo(PhysicalJoin<Plan, Plan> join) {
|
||||
List<EqualTo> eqConjuncts = Lists.newArrayList();
|
||||
if (!join.getCondition().isPresent()) {
|
||||
return eqConjuncts;
|
||||
@ -86,7 +88,7 @@ public class JoinUtils {
|
||||
* Return pair of left used slots and right used slots.
|
||||
*/
|
||||
public static Pair<List<SlotReference>, List<SlotReference>> getOnClauseUsedSlots(
|
||||
PhysicalHashJoin<Plan, Plan> join) {
|
||||
PhysicalJoin<Plan, Plan> join) {
|
||||
Pair<List<SlotReference>, List<SlotReference>> childSlots =
|
||||
new Pair<>(Lists.newArrayList(), Lists.newArrayList());
|
||||
|
||||
@ -114,4 +116,9 @@ public class JoinUtils {
|
||||
|
||||
return childSlots;
|
||||
}
|
||||
|
||||
public static boolean shouldNestedLoopJoin(Join join) {
|
||||
JoinType joinType = join.getJoinType();
|
||||
return (joinType.isInnerJoin() && !join.getCondition().isPresent()) || joinType.isCrossJoin();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,7 @@ import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.AggregateFunction;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.Sum;
|
||||
import org.apache.doris.nereids.trees.plans.FakeJoin;
|
||||
import org.apache.doris.nereids.trees.plans.GroupPlan;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
|
||||
@ -190,11 +191,13 @@ public class StatsCalculatorTest {
|
||||
StatsDeriveResult rightStats = new StatsDeriveResult(rightRowCount, slotColumnStatsMap2);
|
||||
|
||||
EqualTo equalTo = new EqualTo(slot1, slot2);
|
||||
StatsDeriveResult semiJoinStats = JoinEstimation.estimate(leftStats,
|
||||
rightStats, equalTo, JoinType.LEFT_SEMI_JOIN);
|
||||
|
||||
FakeJoin fakeSemiJoin = new FakeJoin(JoinType.LEFT_SEMI_JOIN, Optional.of(equalTo));
|
||||
FakeJoin fakeInnerJoin = new FakeJoin(JoinType.INNER_JOIN, Optional.of(equalTo));
|
||||
|
||||
StatsDeriveResult semiJoinStats = JoinEstimation.estimate(leftStats, rightStats, fakeSemiJoin);
|
||||
Assertions.assertEquals(leftRowCount, semiJoinStats.getRowCount());
|
||||
StatsDeriveResult innerJoinStats = JoinEstimation.estimate(leftStats,
|
||||
rightStats, equalTo, JoinType.INNER_JOIN);
|
||||
StatsDeriveResult innerJoinStats = JoinEstimation.estimate(leftStats, rightStats, fakeInnerJoin);
|
||||
Assertions.assertEquals(2500000, innerJoinStats.getRowCount());
|
||||
}
|
||||
|
||||
@ -240,7 +243,6 @@ public class StatsCalculatorTest {
|
||||
Assertions.assertNotNull(stats.getSlotToColumnStats().get(slot1));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLimit() {
|
||||
List<String> qualifier = new ArrayList<>();
|
||||
@ -276,6 +278,5 @@ public class StatsCalculatorTest {
|
||||
ColumnStats slot1Stats = limitStats.getSlotToColumnStats().get(slot1);
|
||||
Assertions.assertEquals(1, slot1Stats.getNdv());
|
||||
Assertions.assertEquals(1, slot1Stats.getNumNulls());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
// 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.trees.plans;
|
||||
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.plans.algebra.Join;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class FakeJoin implements Join {
|
||||
private final JoinType joinType;
|
||||
private final Optional<Expression> condition;
|
||||
|
||||
public FakeJoin(JoinType joinType, Optional<Expression> condition) {
|
||||
this.joinType = joinType;
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinType getJoinType() {
|
||||
return joinType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Expression> getCondition() {
|
||||
return condition;
|
||||
}
|
||||
}
|
||||
@ -43,3 +43,14 @@
|
||||
|
||||
-- !right_anti_join --
|
||||
|
||||
-- !cross_join --
|
||||
1309892 1 1303 1432 15 19920517 3-MEDIUM 0 24 2959704 5119906 7 2752524 73992 0 19920619 TRUCK 15 Supplier#000000015 DF35PepL5saAK INDIA 0 INDIA ASIA 18-687-542-7601
|
||||
1309892 1 1303 1432 15 19920517 3-MEDIUM 0 24 2959704 5119906 7 2752524 73992 0 19920619 TRUCK 29 Supplier#000000029 VVSymB3fbwaN ARGENTINA4 ARGENTINA AMERICA 11-773-203-7342
|
||||
1309892 1 1303 1432 15 19920517 3-MEDIUM 0 24 2959704 5119906 7 2752524 73992 0 19920619 TRUCK 9 Supplier#000000009 ,gJ6K2MKveYxQT IRAN 6 IRAN MIDDLE EAST 20-338-906-3675
|
||||
1309892 2 1303 1165 9 19920517 3-MEDIUM 0 21 2404899 5119906 8 2212507 68711 7 19920616 RAIL 15 Supplier#000000015 DF35PepL5saAK INDIA 0 INDIA ASIA 18-687-542-7601
|
||||
1309892 2 1303 1165 9 19920517 3-MEDIUM 0 21 2404899 5119906 8 2212507 68711 7 19920616 RAIL 29 Supplier#000000029 VVSymB3fbwaN ARGENTINA4 ARGENTINA AMERICA 11-773-203-7342
|
||||
1309892 2 1303 1165 9 19920517 3-MEDIUM 0 21 2404899 5119906 8 2212507 68711 7 19920616 RAIL 9 Supplier#000000009 ,gJ6K2MKveYxQT IRAN 6 IRAN MIDDLE EAST 20-338-906-3675
|
||||
1310179 6 1312 1455 29 19921110 3-MEDIUM 0 15 1705830 20506457 10 1535247 68233 8 19930114 FOB 15 Supplier#000000015 DF35PepL5saAK INDIA 0 INDIA ASIA 18-687-542-7601
|
||||
1310179 6 1312 1455 29 19921110 3-MEDIUM 0 15 1705830 20506457 10 1535247 68233 8 19930114 FOB 29 Supplier#000000029 VVSymB3fbwaN ARGENTINA4 ARGENTINA AMERICA 11-773-203-7342
|
||||
1310179 6 1312 1455 29 19921110 3-MEDIUM 0 15 1705830 20506457 10 1535247 68233 8 19930114 FOB 9 Supplier#000000009 ,gJ6K2MKveYxQT IRAN 6 IRAN MIDDLE EAST 20-338-906-3675
|
||||
|
||||
|
||||
@ -63,5 +63,9 @@ suite("join") {
|
||||
order_qt_right_anti_join """
|
||||
SELECT * FROM lineorder RIGHT ANTI JOIN supplier ON lineorder.lo_suppkey = supplier.s_suppkey
|
||||
"""
|
||||
|
||||
order_qt_cross_join """
|
||||
SELECT * FROM lineorder CROSS JOIN supplier;
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user