starocean999 commented on code in PR #16676: URL: https://github.com/apache/doris/pull/16676#discussion_r1106665552
########## fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/OuterJoinLAsscomProject.java: ########## @@ -74,95 +69,56 @@ public Rule build() { GroupPlan a = bottomJoin.left(); GroupPlan b = bottomJoin.right(); GroupPlan c = topJoin.right(); - Set<Slot> cOutputSet = c.getOutputSet(); - Set<ExprId> cOutputExprIdSet = c.getOutputExprIdSet(); /* ********** Split projects ********** */ Map<Boolean, List<NamedExpression>> map = JoinReorderUtils.splitProjection(projects, a); - List<NamedExpression> newLeftProjects = map.get(true); - List<NamedExpression> newRightProjects = map.get(false); - Set<ExprId> aExprIdSet = JoinReorderUtils.combineProjectAndChildExprId(a, newLeftProjects); - - /* ********** Conjuncts ********** */ - List<Expression> newTopHashConjuncts = bottomJoin.getHashJoinConjuncts(); - List<Expression> newBottomHashConjuncts = topJoin.getHashJoinConjuncts(); - List<Expression> newTopOtherConjuncts = bottomJoin.getOtherJoinConjuncts(); - List<Expression> newBottomOtherConjuncts = topJoin.getOtherJoinConjuncts(); - - /* ********** replace Conjuncts by projects ********** */ - Map<ExprId, Slot> inputToOutput = new HashMap<>(); - Map<ExprId, Slot> outputToInput = new HashMap<>(); - for (NamedExpression expr : projects) { - if (expr instanceof Alias) { - Alias alias = (Alias) expr; - Slot outputSlot = alias.toSlot(); - Expression child = alias.child(); - // checkProject already confirmed. - Preconditions.checkState(child instanceof Slot); - Slot inputSlot = (Slot) child; - inputToOutput.put(inputSlot.getExprId(), outputSlot); - outputToInput.put(outputSlot.getExprId(), inputSlot); - } + List<NamedExpression> aProjects = map.get(true); + if (aProjects.isEmpty()) { + return null; } - // replace hashConjuncts - newBottomHashConjuncts = JoinUtils.replaceJoinConjuncts(newBottomHashConjuncts, outputToInput); - newTopHashConjuncts = JoinUtils.replaceJoinConjuncts(newTopHashConjuncts, inputToOutput); - // replace otherConjuncts - newBottomOtherConjuncts = JoinUtils.replaceJoinConjuncts(newBottomOtherConjuncts, outputToInput); - newTopOtherConjuncts = JoinUtils.replaceJoinConjuncts(newTopOtherConjuncts, inputToOutput); + List<NamedExpression> bProjects = map.get(false); + Set<ExprId> bProjectsExprIds = bProjects.stream().map(NamedExpression::getExprId) + .collect(Collectors.toSet()); - /* ********** check ********** */ - Set<Slot> acOutputSet = ImmutableSet.<Slot>builder().addAll(a.getOutputSet()) - .addAll(c.getOutputSet()).build(); - if (!Stream.concat(newBottomHashConjuncts.stream(), newBottomOtherConjuncts.stream()) - .allMatch(expr -> { - Set<Slot> inputSlots = expr.getInputSlots(); - return acOutputSet.containsAll(inputSlots); - })) { + // topJoin condition can't contain bProject output. just can (A C) + if (Stream.concat(topJoin.getHashJoinConjuncts().stream(), topJoin.getOtherJoinConjuncts().stream()) + .anyMatch(expr -> Utils.isIntersecting(expr.getInputSlotExprIds(), bProjectsExprIds))) { return null; } - // Add all slots used by OnCondition when projects not empty. - Map<Boolean, Set<Slot>> abOnUsedSlots = Stream.concat( - newTopHashConjuncts.stream(), - newTopOtherConjuncts.stream()) - .flatMap(onExpr -> { - Set<Slot> usedSlotRefs = onExpr.collect(SlotReference.class::isInstance); - return usedSlotRefs.stream(); - }) - .filter(slot -> !cOutputExprIdSet.contains(slot.getExprId())) - .collect(Collectors.partitioningBy( - slot -> aExprIdSet.contains(slot.getExprId()), Collectors.toSet())); - Set<Slot> aUsedSlots = abOnUsedSlots.get(true); - Set<Slot> bUsedSlots = abOnUsedSlots.get(false); + // topJoin condition -> newBottomJoin condition, bottomJoin condition -> newTopJoin condition + JoinReorderHelper helper = new JoinReorderHelper(bottomJoin.getHashJoinConjuncts(), + bottomJoin.getOtherJoinConjuncts(), topJoin.getHashJoinConjuncts(), + topJoin.getOtherJoinConjuncts(), projects, aProjects, bProjects); - JoinUtils.addSlotsUsedByOn(bUsedSlots, newRightProjects); - JoinUtils.addSlotsUsedByOn(aUsedSlots, newLeftProjects); + // Add all slots used by OnCondition when projects not empty. + helper.addSlotsUsedByOn(JoinReorderUtils.combineProjectAndChildExprId(a, helper.newLeftProjects), + Collections.EMPTY_SET); - if (!newLeftProjects.isEmpty()) { - Set<Slot> nullableCOutputSet = forceToNullable(cOutputSet); - newLeftProjects.addAll(nullableCOutputSet); - } + aProjects.addAll(forceToNullable(c.getOutputSet())); Review Comment: don't need to call forceToNullable if old top join is inner join -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org