You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2022/10/31 08:21:36 UTC

[doris] branch branch-1.1-lts updated: [cherry-pick](join) fix incorrect result when using anti join with other join predicates (#13812)

This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-1.1-lts
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-1.1-lts by this push:
     new a853d69bb1 [cherry-pick](join) fix incorrect result when using anti join with other join predicates (#13812)
a853d69bb1 is described below

commit a853d69bb147ab3d11aa960952c8e63446cc6c55
Author: luozenglin <37...@users.noreply.github.com>
AuthorDate: Mon Oct 31 16:21:29 2022 +0800

    [cherry-pick](join) fix incorrect result when using anti join with other join predicates (#13812)
---
 .../java/org/apache/doris/analysis/Analyzer.java   | 29 +++++++++++++++++++++-
 .../apache/doris/planner/SingleNodePlanner.java    |  7 +++---
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
index 14a357f4b0..c0c71289ea 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
@@ -264,6 +264,8 @@ public class Analyzer {
         // corresponding value could be an empty list. There is no entry for non-outer joins.
         public final Map<TupleId, List<ExprId>> conjunctsByOjClause = Maps.newHashMap();
 
+        public final Map<TupleId, List<ExprId>> conjunctsByAntiJoinClause = Maps.newHashMap();
+
         // map from registered conjunct to its containing outer join On clause (represented
         // by its right-hand side table ref); only conjuncts that can only be correctly
         // evaluated by the originating outer join are registered here
@@ -1262,6 +1264,27 @@ public class Analyzer {
         return result;
     }
 
+    /**
+     * Return all unassigned conjuncts of the anti join referenced by
+     * right-hand side table ref.
+     */
+    public List<Expr> getUnassignedAntiJoinConjuncts(TableRef ref) {
+        Preconditions.checkState(ref.getJoinOp().isAntiJoin());
+        List<Expr> result = Lists.newArrayList();
+        List<ExprId> candidates = globalState.conjunctsByAntiJoinClause.get(ref.getId());
+        if (candidates == null) {
+            return result;
+        }
+        for (ExprId conjunctId : candidates) {
+            if (!globalState.assignedConjuncts.contains(conjunctId)) {
+                Expr e = globalState.conjuncts.get(conjunctId);
+                Preconditions.checkState(e != null);
+                result.add(e);
+            }
+        }
+        return result;
+    }
+
     /**
      * Returns true if 'e' must be evaluated after or by a join node. Note that it may
      * still be safe to evaluate 'e' elsewhere as well, but in any case 'e' must be
@@ -1507,6 +1530,10 @@ public class Analyzer {
             }
             if (rhsRef.getJoinOp().isSemiJoin()) {
                 globalState.sjClauseByConjunct.put(conjunct.getId(), rhsRef);
+                if (rhsRef.getJoinOp().isAntiJoin()) {
+                    globalState.conjunctsByAntiJoinClause.computeIfAbsent(rhsRef.getId(), k -> Lists.newArrayList())
+                            .add(conjunct.getId());
+                }
             }
             if (rhsRef.getJoinOp().isInnerJoin()) {
                 globalState.ijClauseByConjunct.put(conjunct.getId(), rhsRef);
@@ -1524,7 +1551,7 @@ public class Analyzer {
      * Throws an AnalysisException if there is an error evaluating `conjunct`
      */
     private void markConstantConjunct(Expr conjunct, boolean fromHavingClause) throws AnalysisException {
-        if (!conjunct.isConstant() || isOjConjunct(conjunct)) {
+        if (!conjunct.isConstant() || isOjConjunct(conjunct) || isAntiJoinedConjunct(conjunct)) {
             return;
         }
         if ((!fromHavingClause && !hasEmptySpjResultSet_) || (fromHavingClause && !hasEmptyResultSet_)) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index b233d9ce9f..30dc5eb27e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -1858,12 +1858,13 @@ public class SingleNodePlanner {
             // Also assign conjuncts from On clause. All remaining unassigned conjuncts
             // that can be evaluated by this join are assigned in createSelectPlan().
             ojConjuncts = analyzer.getUnassignedOjConjuncts(innerRef);
-            analyzer.markConjunctsAssigned(ojConjuncts);
-        } else if (innerRef.getJoinOp().isSemiAntiJoin()) {
+        } else if (innerRef.getJoinOp().isAntiJoin()) {
+            ojConjuncts = analyzer.getUnassignedAntiJoinConjuncts(innerRef);
+        } else if (innerRef.getJoinOp().isSemiJoin()) {
             final List<TupleId> tupleIds = innerRef.getAllTupleIds();
             ojConjuncts = analyzer.getUnassignedConjuncts(tupleIds, false);
-            analyzer.markConjunctsAssigned(ojConjuncts);
         }
+        analyzer.markConjunctsAssigned(ojConjuncts);
 
         HashJoinNode result =
                 new HashJoinNode(ctx.getNextNodeId(), outer, inner, innerRef, eqJoinConjuncts,


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org