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

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

commit 5e97bce8c01ff98118c7625074aa4a9be5882d60
Author: starocean999 <40539150+starocean...@users.noreply.github.com>
AuthorDate: Tue Jan 17 20:25:00 2023 +0800

    [fix](fe)fix anti join bug (#15955)
    
    * [fix](fe)fix anti join bug
    
    * fix fe ut
---
 .../java/org/apache/doris/analysis/Analyzer.java   | 93 ++++++++++++++++------
 .../org/apache/doris/analysis/JoinOperator.java    | 13 +++
 .../apache/doris/planner/SingleNodePlanner.java    |  9 +--
 .../java/org/apache/doris/planner/PlannerTest.java |  2 +-
 .../org/apache/doris/planner/QueryPlanTest.java    |  2 +-
 regression-test/data/query_p0/join/test_join.out   | 80 +++++++++++++++++++
 .../suites/query_p0/join/test_join.groovy          | 10 ++-
 7 files changed, 178 insertions(+), 31 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 946718b2c6..649f054e39 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
@@ -358,7 +358,9 @@ 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();
+        public final Map<TupleId, List<ExprId>> 
conjunctsByAntiJoinNullAwareClause = Maps.newHashMap();
+
+        public final Map<TupleId, List<ExprId>> 
conjunctsBySemiAntiJoinNoNullAwareClause = 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
@@ -1387,10 +1389,27 @@ public class Analyzer {
      * 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());
+    public List<Expr> getUnassignedAntiJoinNullAwareConjuncts(TableRef ref) {
+        Preconditions.checkState(ref.getJoinOp().isAntiJoinNullAware());
+        List<Expr> result = Lists.newArrayList();
+        List<ExprId> candidates = 
globalState.conjunctsByAntiJoinNullAwareClause.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;
+    }
+
+    public List<Expr> getUnassignedSemiAntiJoinNoNullAwareConjuncts(TableRef 
ref) {
+        
Preconditions.checkState(ref.getJoinOp().isSemiOrAntiJoinNoNullAware());
         List<Expr> result = Lists.newArrayList();
-        List<ExprId> candidates = 
globalState.conjunctsByAntiJoinClause.get(ref.getId());
+        List<ExprId> candidates = 
globalState.conjunctsBySemiAntiJoinNoNullAwareClause.get(ref.getId());
         if (candidates == null) {
             return result;
         }
@@ -1480,6 +1499,30 @@ public class Analyzer {
         return (tblRef.getJoinOp().isAntiJoin()) ? tblRef : null;
     }
 
+    public boolean isAntiJoinedNullAwareConjunct(Expr e) {
+        return getAntiJoinNullAwareRef(e) != null;
+    }
+
+    private TableRef getAntiJoinNullAwareRef(Expr e) {
+        TableRef tblRef = globalState.sjClauseByConjunct.get(e.getId());
+        if (tblRef == null) {
+            return null;
+        }
+        return (tblRef.getJoinOp().isAntiJoinNullAware()) ? tblRef : null;
+    }
+
+    public boolean isAntiJoinedNoNullAwareConjunct(Expr e) {
+        return getAntiJoinNoNullAwareRef(e) != null;
+    }
+
+    public TableRef getAntiJoinNoNullAwareRef(Expr e) {
+        TableRef tblRef = globalState.sjClauseByConjunct.get(e.getId());
+        if (tblRef == null) {
+            return null;
+        }
+        return (tblRef.getJoinOp().isAntiJoinNoNullAware()) ? tblRef : null;
+    }
+
     public boolean isFullOuterJoined(TupleId tid) {
         return globalState.fullOuterJoinedTupleIds.containsKey(tid);
     }
@@ -1697,11 +1740,14 @@ public class Analyzer {
                 globalState.ojClauseByConjunct.put(conjunct.getId(), rhsRef);
                 ojConjuncts.add(conjunct.getId());
             }
-            if (rhsRef.getJoinOp().isSemiJoin()) {
+            if (rhsRef.getJoinOp().isSemiAntiJoin()) {
                 globalState.sjClauseByConjunct.put(conjunct.getId(), rhsRef);
-                if (rhsRef.getJoinOp().isAntiJoin()) {
-                    
globalState.conjunctsByAntiJoinClause.computeIfAbsent(rhsRef.getId(), k -> 
Lists.newArrayList())
-                            .add(conjunct.getId());
+                if (rhsRef.getJoinOp().isAntiJoinNullAware()) {
+                    
globalState.conjunctsByAntiJoinNullAwareClause.computeIfAbsent(rhsRef.getId(),
+                            k -> Lists.newArrayList()).add(conjunct.getId());
+                } else {
+                    
globalState.conjunctsBySemiAntiJoinNoNullAwareClause.computeIfAbsent(rhsRef.getId(),
+                            k -> Lists.newArrayList()).add(conjunct.getId());
                 }
             }
             if (rhsRef.getJoinOp().isInnerJoin()) {
@@ -1721,7 +1767,7 @@ public class Analyzer {
      */
     private void markConstantConjunct(Expr conjunct, boolean fromHavingClause)
             throws AnalysisException {
-        if (!conjunct.isConstant() || isOjConjunct(conjunct) || 
isAntiJoinedConjunct(conjunct)) {
+        if (!conjunct.isConstant() || isOjConjunct(conjunct)) {
             return;
         }
         if ((!fromHavingClause && !hasEmptySpjResultSet)
@@ -1738,24 +1784,25 @@ public class Analyzer {
                     conjunct.analyze(this);
                 }
                 final Expr newConjunct = conjunct.getResultValue();
-                if (newConjunct instanceof BoolLiteral) {
-                    final BoolLiteral value = (BoolLiteral) newConjunct;
-                    if (!value.getValue()) {
-                        if (fromHavingClause) {
-                            hasEmptyResultSet = true;
-                        } else {
-                            hasEmptySpjResultSet = true;
-                        }
+                if (newConjunct instanceof BoolLiteral || newConjunct 
instanceof NullLiteral) {
+                    boolean evalResult = true;
+                    if (newConjunct instanceof BoolLiteral) {
+                        evalResult = ((BoolLiteral) newConjunct).getValue();
+                    } else {
+                        evalResult = false;
                     }
-                    markConjunctAssigned(conjunct);
-                }
-                if (newConjunct instanceof NullLiteral) {
                     if (fromHavingClause) {
-                        hasEmptyResultSet = true;
+                        hasEmptyResultSet = !evalResult;
                     } else {
-                        hasEmptySpjResultSet = true;
+                        if (isAntiJoinedNoNullAwareConjunct(conjunct)) {
+                            hasEmptySpjResultSet = evalResult;
+                        } else {
+                            hasEmptySpjResultSet = !evalResult;
+                        }
+                    }
+                    if (hasEmptyResultSet || hasEmptySpjResultSet) {
+                        markConjunctAssigned(conjunct);
                     }
-                    markConjunctAssigned(conjunct);
                 }
             } catch (AnalysisException ex) {
                 throw new AnalysisException("Error evaluating \"" + 
conjunct.toSql() + "\"", ex);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/JoinOperator.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/JoinOperator.java
index de33961db1..08c0321b25 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/JoinOperator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/JoinOperator.java
@@ -71,6 +71,19 @@ public enum JoinOperator {
                 || this == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN;
     }
 
+    public boolean isSemiOrAntiJoinNoNullAware() {
+        return this == JoinOperator.LEFT_SEMI_JOIN || this == 
JoinOperator.LEFT_ANTI_JOIN
+                || this == JoinOperator.RIGHT_SEMI_JOIN || this == 
JoinOperator.RIGHT_ANTI_JOIN;
+    }
+
+    public boolean isAntiJoinNullAware() {
+        return this == JoinOperator.NULL_AWARE_LEFT_ANTI_JOIN;
+    }
+
+    public boolean isAntiJoinNoNullAware() {
+        return this == JoinOperator.LEFT_ANTI_JOIN || this == 
JoinOperator.RIGHT_ANTI_JOIN;
+    }
+
     public boolean isLeftSemiJoin() {
         return this.thriftJoinOp == TJoinOp.LEFT_SEMI_JOIN;
     }
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 e6ab97d2a4..854da5ddcc 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
@@ -2069,11 +2069,10 @@ 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);
-        } 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);
+        } else if (innerRef.getJoinOp().isAntiJoinNullAware()) {
+            ojConjuncts = 
analyzer.getUnassignedAntiJoinNullAwareConjuncts(innerRef);
+        } else if (innerRef.getJoinOp().isSemiOrAntiJoinNoNullAware()) {
+            ojConjuncts = 
analyzer.getUnassignedSemiAntiJoinNoNullAwareConjuncts(innerRef);
         }
         analyzer.markConjunctsAssigned(ojConjuncts);
         if (eqJoinConjuncts.isEmpty() || innerRef.isMark()) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
index 3d2293c670..2b5e0c3266 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java
@@ -405,7 +405,7 @@ public class PlannerTest extends TestWithFeService {
         compare.accept("select * from db1.tbl2 where k1 = 2.0", "select * from 
db1.tbl2 where k1 = 2");
         compare.accept("select * from db1.tbl2 where k1 = 2.1", "select * from 
db1.tbl2 where 2 = 2.1");
         compare.accept("select * from db1.tbl2 where k1 != 2.0", "select * 
from db1.tbl2 where k1 != 2");
-        compare.accept("select * from db1.tbl2 where k1 != 2.1", "select * 
from db1.tbl2");
+        compare.accept("select * from db1.tbl2 where k1 != 2.1", "select * 
from db1.tbl2 where TRUE");
         compare.accept("select * from db1.tbl2 where k1 <= 2.0", "select * 
from db1.tbl2 where k1 <= 2");
         compare.accept("select * from db1.tbl2 where k1 <= 2.1", "select * 
from db1.tbl2 where k1 <= 2");
         compare.accept("select * from db1.tbl2 where k1 >= 2.0", "select * 
from db1.tbl2 where k1 >= 2");
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
index 4f41e70c45..9d8e560c11 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
@@ -1025,7 +1025,7 @@ public class QueryPlanTest extends TestWithFeService {
         String explainString = getSQLPlanOrErrorMsg("explain " + sql);
         Assert.assertTrue(explainString.contains("PLAN FRAGMENT"));
         Assert.assertTrue(explainString.contains("NESTED LOOP JOIN"));
-        Assert.assertTrue(!explainString.contains("PREDICATES"));
+        Assert.assertTrue(!explainString.contains("PREDICATES") || 
explainString.contains("PREDICATES: TRUE"));
     }
 
     @Test
diff --git a/regression-test/data/query_p0/join/test_join.out 
b/regression-test/data/query_p0/join/test_join.out
index c19bf29042..94d5e31dae 100644
--- a/regression-test/data/query_p0/join/test_join.out
+++ b/regression-test/data/query_p0/join/test_join.out
@@ -2714,3 +2714,83 @@ false    true    true    false   false
 5      2.200   null    \N      2019-09-09T00:00        8.9     2       \N      
2       \N      \N      8.9
 5      2.200   null    \N      2019-09-09T00:00        8.9     3       \N      
null    2019-09-09      \N      8.9
 
+-- !sql --
+\N
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
+-- !sql --
+
+-- !sql --
+
+-- !sql --
+\N
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
+-- !sql --
+\N
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
+-- !sql --
+
+-- !sql --
+
+-- !sql --
+\N
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+
diff --git a/regression-test/suites/query_p0/join/test_join.groovy 
b/regression-test/suites/query_p0/join/test_join.groovy
index 146ab61de4..5137156f6a 100644
--- a/regression-test/suites/query_p0/join/test_join.groovy
+++ b/regression-test/suites/query_p0/join/test_join.groovy
@@ -1219,7 +1219,15 @@ suite("test_join", "query,p0") {
     sql"""drop table ${table_3}"""
     sql"""drop table ${table_4}"""
 
-
+    qt_sql """select k1 from baseall left semi join test on true order by 
k1;"""
+    qt_sql """select k1 from baseall left semi join test on false order by 
k1;"""
+    qt_sql """select k1 from baseall left anti join test on true order by 
k1;"""
+    qt_sql """select k1 from baseall left anti join test on false order by 
k1;"""
+
+    qt_sql """select k1 from test right semi join baseall on true order by 
k1;"""
+    qt_sql """select k1 from test right semi join baseall on false order by 
k1;"""
+    qt_sql """select k1 from test right anti join baseall on true order by 
k1;"""
+    qt_sql """select k1 from test right anti join baseall on false order by 
k1;"""
 
     // test bucket shuffle join, github issue #6171
     sql"""create database if not exists test_issue_6171"""


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

Reply via email to