[enhancement](nereids) show nullaware semi join in plan (#31738)

This commit is contained in:
starocean999
2024-03-07 10:56:54 +08:00
committed by yiguolei
parent 5905ffa1da
commit 9d5c51f5c3
2 changed files with 16 additions and 17 deletions

View File

@ -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);

View File

@ -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);