You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by st...@apache.org on 2023/06/19 15:43:47 UTC

[doris] branch master updated: [fix](nereids)SubqueryToApply rule lost is null condition (#20971)

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

starocean999 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new e6f50c04f1 [fix](nereids)SubqueryToApply rule lost is null condition (#20971)
e6f50c04f1 is described below

commit e6f50c04f10a0656d3a2fe337c603ef672d85176
Author: starocean999 <40...@users.noreply.github.com>
AuthorDate: Mon Jun 19 23:43:40 2023 +0800

    [fix](nereids)SubqueryToApply rule lost is null condition (#20971)
    
    * [fix](nereids)SubqueryToApply rule lost is null condition
---
 .../nereids/rules/analysis/SubqueryToApply.java    | 39 +++++++++++++++++-----
 .../java/org/apache/doris/planner/PlannerTest.java | 22 ++++++------
 .../nereids_syntax_p0/join_subquery_to_apply.out   |  3 ++
 .../join_subquery_to_apply.groovy                  | 30 +++++++++++++++++
 4 files changed, 75 insertions(+), 19 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubqueryToApply.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubqueryToApply.java
index 58f2196981..fb39794c23 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubqueryToApply.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SubqueryToApply.java
@@ -29,6 +29,7 @@ import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
 import org.apache.doris.nereids.trees.expressions.Exists;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.InSubquery;
+import org.apache.doris.nereids.trees.expressions.IsNull;
 import org.apache.doris.nereids.trees.expressions.MarkJoinSlotReference;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
 import org.apache.doris.nereids.trees.expressions.Not;
@@ -356,6 +357,21 @@ public class SubqueryToApply implements AnalysisRuleFactory {
             return visit(not, context);
         }
 
+        @Override
+        public Expression visitIsNull(IsNull isNull, SubqueryContext context) {
+            // Need to re-update scalarSubQuery unequal conditions into subqueryCorrespondingConject
+            if (isNull.child() instanceof BinaryOperator
+                    && (((BinaryOperator) isNull.child()).left().containsType(ScalarSubquery.class)
+                    || ((BinaryOperator) isNull.child()).right().containsType(ScalarSubquery.class))) {
+                Expression newChild = replace(isNull.child(), context);
+                ScalarSubquery subquery = collectScalarSubqueryForBinaryOperator((BinaryOperator) isNull.child());
+                context.updateSubqueryCorrespondingConjunctIsNull(subquery);
+                return context.getSubqueryToMarkJoinSlotValue(subquery).isPresent() ? newChild : new IsNull(newChild);
+            }
+
+            return visit(isNull, context);
+        }
+
         @Override
         public Expression visitBinaryOperator(BinaryOperator binaryOperator, SubqueryContext context) {
             boolean atLeastOneChildContainsScalarSubquery =
@@ -403,39 +419,46 @@ public class SubqueryToApply implements AnalysisRuleFactory {
             subqueryExprs.forEach(subqueryExpr -> subqueryToMarkJoinSlot.put(subqueryExpr, Optional.empty()));
         }
 
-        public Map<SubqueryExpr, Optional<MarkJoinSlotReference>> getSubqueryToMarkJoinSlot() {
+        private Map<SubqueryExpr, Optional<MarkJoinSlotReference>> getSubqueryToMarkJoinSlot() {
             return subqueryToMarkJoinSlot;
         }
 
-        public Map<SubqueryExpr, Expression> getSubqueryCorrespondingConjunct() {
+        private Map<SubqueryExpr, Expression> getSubqueryCorrespondingConjunct() {
             return subqueryCorrespondingConjunct;
         }
 
-        public Optional<MarkJoinSlotReference> getSubqueryToMarkJoinSlotValue(SubqueryExpr subqueryExpr) {
+        private Optional<MarkJoinSlotReference> getSubqueryToMarkJoinSlotValue(SubqueryExpr subqueryExpr) {
             return subqueryToMarkJoinSlot.get(subqueryExpr);
         }
 
-        public void setSubqueryToMarkJoinSlot(SubqueryExpr subquery,
+        private void setSubqueryToMarkJoinSlot(SubqueryExpr subquery,
                                               Optional<MarkJoinSlotReference> markJoinSlotReference) {
             subqueryToMarkJoinSlot.put(subquery, markJoinSlotReference);
         }
 
-        public void setSubqueryCorrespondingConject(SubqueryExpr subquery,
+        private void setSubqueryCorrespondingConject(SubqueryExpr subquery,
                                                     Expression expression) {
             subqueryCorrespondingConjunct.put(subquery, expression);
         }
 
-        public boolean onlySingleSubquery() {
+        private boolean onlySingleSubquery() {
             return subqueryToMarkJoinSlot.size() == 1;
         }
 
-        public void updateSubqueryCorrespondingConjunctInNot(SubqueryExpr subquery) {
+        private void updateSubqueryCorrespondingConjunctInNot(SubqueryExpr subquery) {
             if (subqueryCorrespondingConjunct.containsKey(subquery)) {
                 subqueryCorrespondingConjunct.replace(subquery,
                     new Not(subqueryCorrespondingConjunct.get(subquery)));
             }
         }
 
+        private void updateSubqueryCorrespondingConjunctIsNull(SubqueryExpr subquery) {
+            if (subqueryCorrespondingConjunct.containsKey(subquery)) {
+                subqueryCorrespondingConjunct.replace(subquery,
+                        new IsNull(subqueryCorrespondingConjunct.get(subquery)));
+            }
+        }
+
         /**
          * For scalarSubQuery and MarkJoin, it will be replaced by markSlotReference
          *  e.g.
@@ -443,7 +466,7 @@ public class SubqueryToApply implements AnalysisRuleFactory {
          *  -->
          *  logicalFilter(predicate=$c$1 or $c$2)
          */
-        public Expression replaceBinaryOperator(BinaryOperator binaryOperator,
+        private Expression replaceBinaryOperator(BinaryOperator binaryOperator,
                                                 Expression left,
                                                 Expression right,
                                                 boolean isProject) {
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 9f5db2ff27..3893e69fce 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
@@ -402,18 +402,18 @@ public class PlannerTest extends TestWithFeService {
             Assertions.assertEquals(plan1, plan2);
         };
 
-        compare.accept("select * from db1.tbl2 where k1 = 2.0", "select * from db1.tbl2 where k1 = 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2");
         compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */ * from db1.tbl2 where k1 = 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */ * 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 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");
-        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");
-        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");
-        compare.accept("select * from db1.tbl2 where k1 > 2.1", "select * from db1.tbl2 where k1 > 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 != 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where TRUE");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 >= 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 < 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 <= 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2.0", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
+        compare.accept("select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2.1", "select /*+ SET_VAR(enable_nereids_planner=false) */* from db1.tbl2 where k1 > 2");
     }
 
     @Test
diff --git a/regression-test/data/nereids_syntax_p0/join_subquery_to_apply.out b/regression-test/data/nereids_syntax_p0/join_subquery_to_apply.out
new file mode 100644
index 0000000000..9c9c4c6c8a
--- /dev/null
+++ b/regression-test/data/nereids_syntax_p0/join_subquery_to_apply.out
@@ -0,0 +1,3 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !sql --
+
diff --git a/regression-test/suites/nereids_syntax_p0/join_subquery_to_apply.groovy b/regression-test/suites/nereids_syntax_p0/join_subquery_to_apply.groovy
new file mode 100644
index 0000000000..44e97f4e90
--- /dev/null
+++ b/regression-test/suites/nereids_syntax_p0/join_subquery_to_apply.groovy
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("join_subquery_to_apply") {
+    sql 'set enable_nereids_planner=true'
+    sql 'set enable_fallback_to_original_planner=false'
+
+    qt_sql"""
+        select 
+        ref_25.`user_name` as c3
+        from
+        (select 'zhangsan' as user_name) as ref_25 
+        where
+        bitxor(cast(find_in_set(cast(coalesce(hex(cast((select 211985) as bigint)), ref_25.`user_name`) as varchar), 'zhangsan') as int), 1) is NULL;
+    """
+}


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