[enhancement](nereids) show nullaware semi join in plan (#31738)
This commit is contained in:
@ -28,6 +28,7 @@ import org.apache.doris.analysis.FunctionCallExpr;
|
||||
import org.apache.doris.analysis.GroupByClause.GroupingType;
|
||||
import org.apache.doris.analysis.GroupingInfo;
|
||||
import org.apache.doris.analysis.IsNullPredicate;
|
||||
import org.apache.doris.analysis.JoinOperator;
|
||||
import org.apache.doris.analysis.OrderByElement;
|
||||
import org.apache.doris.analysis.OutFileClause;
|
||||
import org.apache.doris.analysis.SlotDescriptor;
|
||||
@ -1227,6 +1228,7 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla
|
||||
List<Expr> markConjuncts = ImmutableList.of();
|
||||
boolean isHashJoinConjunctsEmpty = hashJoin.getHashJoinConjuncts().isEmpty();
|
||||
boolean isMarkJoinConjunctsEmpty = hashJoin.getMarkJoinConjuncts().isEmpty();
|
||||
JoinOperator joinOperator = JoinType.toJoinOperator(joinType);
|
||||
if (isHashJoinConjunctsEmpty) {
|
||||
// if hash join conjuncts is empty, means mark join conjuncts must be EqualPredicate
|
||||
// BE should use mark join conjuncts to build hash table
|
||||
@ -1236,10 +1238,20 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor<PlanFragment, Pla
|
||||
.map(e -> JoinUtils.swapEqualToForChildrenOrder(e, hashJoin.left().getOutputSet()))
|
||||
.map(e -> ExpressionTranslator.translate(e, context))
|
||||
.collect(Collectors.toList());
|
||||
// in order to process semi/anti join with no hash conjunct and having mark conjunct effeciently
|
||||
// we can use mark conjunct as hash conjunct with slight different behavior if meets null values
|
||||
// so we use null aware semi/anti join to indicate it's a null aware hash conjunct
|
||||
// it's unnecessary to introduce new join type like NULL_AWARE_LEFT_SEMI_JOIN in nereids
|
||||
// so we translate the join type here to let be known if the hash conjunct is null aware
|
||||
if (joinOperator == JoinOperator.LEFT_ANTI_JOIN) {
|
||||
joinOperator = JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN;
|
||||
} else if (joinOperator == JoinOperator.LEFT_SEMI_JOIN) {
|
||||
joinOperator = JoinOperator.NULL_AWARE_LEFT_SEMI_JOIN;
|
||||
}
|
||||
}
|
||||
|
||||
HashJoinNode hashJoinNode = new HashJoinNode(context.nextPlanNodeId(), leftPlanRoot,
|
||||
rightPlanRoot, JoinType.toJoinOperator(joinType), execEqConjuncts, Lists.newArrayList(), markConjuncts,
|
||||
rightPlanRoot, joinOperator, execEqConjuncts, Lists.newArrayList(), markConjuncts,
|
||||
null, null, null, hashJoin.isMarkJoin());
|
||||
hashJoinNode.setNereidsId(hashJoin.getId());
|
||||
hashJoinNode.setDistributeExprLists(distributeExprLists);
|
||||
|
||||
@ -782,11 +782,8 @@ public class HashJoinNode extends JoinNodeBase {
|
||||
|
||||
if (markJoinConjuncts != null) {
|
||||
if (eqJoinConjuncts.isEmpty()) {
|
||||
Preconditions.checkState(joinOp == JoinOperator.LEFT_SEMI_JOIN
|
||||
|| joinOp == JoinOperator.LEFT_ANTI_JOIN);
|
||||
if (joinOp == JoinOperator.LEFT_SEMI_JOIN || joinOp == JoinOperator.LEFT_ANTI_JOIN) {
|
||||
msg.hash_join_node.join_op = transformJoinOperator().toThrift();
|
||||
}
|
||||
Preconditions.checkState(joinOp == JoinOperator.NULL_AWARE_LEFT_SEMI_JOIN
|
||||
|| joinOp == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN);
|
||||
// because eqJoinConjuncts mustn't be empty in thrift
|
||||
// we have to use markJoinConjuncts instead
|
||||
for (Expr e : markJoinConjuncts) {
|
||||
@ -969,19 +966,9 @@ public class HashJoinNode extends JoinNodeBase {
|
||||
}
|
||||
}
|
||||
|
||||
private JoinOperator transformJoinOperator() {
|
||||
boolean transformToNullAware = markJoinConjuncts != null && eqJoinConjuncts.isEmpty();
|
||||
if (joinOp == JoinOperator.LEFT_ANTI_JOIN && transformToNullAware) {
|
||||
return JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN;
|
||||
} else if (joinOp == JoinOperator.LEFT_SEMI_JOIN && transformToNullAware) {
|
||||
return JoinOperator.NULL_AWARE_LEFT_SEMI_JOIN;
|
||||
}
|
||||
return joinOp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullAwareLeftAntiJoin() {
|
||||
if (transformJoinOperator() == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN) {
|
||||
if (joinOp == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN) {
|
||||
return true;
|
||||
}
|
||||
return children.stream().anyMatch(PlanNode::isNullAwareLeftAntiJoin);
|
||||
|
||||
Reference in New Issue
Block a user