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

yiguolei 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 9945067e3c [Bug](function) make VcompoundPred optimization work well 
(#19870)
9945067e3c is described below

commit 9945067e3c9bc6a985bb834c631b22e1ef17fafd
Author: Pxl <[email protected]>
AuthorDate: Mon May 22 18:32:17 2023 +0800

    [Bug](function) make VcompoundPred optimization work well (#19870)
    
    make VcompoundPred optimization work well
    #19818 this pr try to enable VcompoundPred optimization but get wrong 
result on tpcds q28.
    The reason is some nullable logic on mysql need special handling.
    
    mysql [regression_test_tpcds_sf1_p1]>select null and false;
    +----------------+
    | NULL AND FALSE |
    +----------------+
    |              0 |
    +----------------+
    1 row in set (0.00 sec)
    
    mysql [regression_test_tpcds_sf1_p1]>select null and true;
    +---------------+
    | NULL AND TRUE |
    +---------------+
    | NULL          |
    +---------------+
    1 row in set (0.00 sec)
    
    mysql [regression_test_tpcds_sf1_p1]>select null or false;
    +---------------+
    | NULL OR FALSE |
    +---------------+
    | NULL          |
    +---------------+
    1 row in set (0.00 sec)
    
    mysql [regression_test_tpcds_sf1_p1]>select null or true;
    +--------------+
    | NULL OR TRUE |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.00 sec)
---
 be/src/vec/exprs/vcompound_pred.h                  | 74 +++++++++++++---------
 .../data/query_p0/sql_functions/test_predicate.out | 48 ++++++++++++++
 .../query_p0/sql_functions/test_predicate.groovy   | 57 +++++++++++++++++
 3 files changed, 148 insertions(+), 31 deletions(-)

diff --git a/be/src/vec/exprs/vcompound_pred.h 
b/be/src/vec/exprs/vcompound_pred.h
index 9ce992d0ec..47f12fa13e 100644
--- a/be/src/vec/exprs/vcompound_pred.h
+++ b/be/src/vec/exprs/vcompound_pred.h
@@ -54,9 +54,13 @@ public:
 
     const std::string& expr_name() const override { return _expr_name; }
 
-    Status execute(VExprContext* context, doris::vectorized::Block* block,
+    Status execute(VExprContext* context, vectorized::Block* block,
                    int* result_column_id) override {
-        if (children().size() == 1 || !_all_child_is_compound_and_not_const()) 
{
+        if (children().size() == 1 || !_all_child_is_compound_and_not_const() 
||
+            _children[0]->is_nullable() || _children[1]->is_nullable()) {
+            // TODO:
+            // When the child is nullable, make the optimization also take 
effect, and the processing of this piece may be more complicated
+            // https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html
             return VectorizedFnCall::execute(context, block, result_column_id);
         }
 
@@ -65,15 +69,14 @@ public:
         RETURN_IF_ERROR(_children[0]->execute(context, block, &lhs_id));
         ColumnPtr lhs_column = block->get_by_position(lhs_id).column;
 
-        ColumnPtr rhs_column = nullptr;
-
         size_t size = lhs_column->size();
         uint8* __restrict data = _get_raw_data(lhs_column);
         int filted = simd::count_zero_num((int8_t*)data, size);
         bool full = filted == 0;
         bool empty = filted == size;
 
-        const uint8* __restrict data_rhs = nullptr;
+        ColumnPtr rhs_column = nullptr;
+        uint8* __restrict data_rhs = nullptr;
         bool full_rhs = false;
         bool empty_rhs = false;
 
@@ -82,15 +85,6 @@ public:
                 RETURN_IF_ERROR(_children[1]->execute(context, block, 
&rhs_id));
                 rhs_column = block->get_by_position(rhs_id).column;
                 data_rhs = _get_raw_data(rhs_column);
-                if (!empty) {
-                    if (const uint8* null_map =
-                                
_get_null_map(block->get_by_position(rhs_id).column);
-                        null_map != nullptr) {
-                        for (size_t i = 0; i < size; i++) {
-                            data[i] &= !null_map[i];
-                        }
-                    }
-                }
                 int filted = simd::count_zero_num((int8_t*)data_rhs, size);
                 full_rhs = filted == 0;
                 empty_rhs = filted == size;
@@ -99,34 +93,54 @@ public:
         };
 
         if (_op == TExprOpcode::COMPOUND_AND) {
-            if (!empty) { // empty and any = empty, so lhs should not empty
+            if (empty) {
+                // empty and any = empty, return lhs
+                *result_column_id = lhs_id;
+            } else {
                 RETURN_IF_ERROR(get_rhs_colum());
-                if (empty_rhs) { // any and empty = empty
+
+                if (full) {
+                    // full and any = any, return rhs
                     *result_column_id = rhs_id;
-                    return Status::OK();
-                } else if (!full_rhs) { // any and full = any, so rhs should 
not full.
+                } else if (empty_rhs) {
+                    // any and empty = empty, return rhs
+                    *result_column_id = rhs_id;
+                } else if (full_rhs) {
+                    // any and full = any, return lhs
+                    *result_column_id = lhs_id;
+                } else {
+                    *result_column_id = lhs_id;
                     for (size_t i = 0; i < size; i++) {
                         data[i] &= data_rhs[i];
                     }
                 }
             }
         } else if (_op == TExprOpcode::COMPOUND_OR) {
-            if (!full) { // full or any = full, so lhs should not full
+            if (full) {
+                // full or any = full, return lhs
+                *result_column_id = lhs_id;
+            } else {
                 RETURN_IF_ERROR(get_rhs_colum());
-                if (full_rhs) { // any or full = full
+                if (empty) {
+                    // empty or any = any, return rhs
+                    *result_column_id = rhs_id;
+                } else if (full_rhs) {
+                    // any or full = full, return rhs
                     *result_column_id = rhs_id;
-                    return Status::OK();
-                } else if (!empty_rhs) { // any or empty = any, so rhs should 
not empty
+                } else if (empty_rhs) {
+                    // any or empty = any, return lhs
+                    *result_column_id = lhs_id;
+                } else {
+                    *result_column_id = lhs_id;
                     for (size_t i = 0; i < size; i++) {
                         data[i] |= data_rhs[i];
                     }
                 }
             }
         } else {
-            LOG(FATAL) << "Compound operator must be AND or OR.";
+            return Status::InternalError("Compound operator must be AND or 
OR.");
         }
 
-        *result_column_id = lhs_id;
         return Status::OK();
     }
 
@@ -151,28 +165,26 @@ private:
                 return false;
             }
         }
-        return false;
+        return true;
     }
 
     uint8* _get_raw_data(ColumnPtr column) const {
         if (column->is_nullable()) {
-            return reinterpret_cast<ColumnUInt8*>(
+            return assert_cast<ColumnUInt8*>(
                            
assert_cast<ColumnNullable*>(column->assume_mutable().get())
                                    ->get_nested_column_ptr()
                                    .get())
                     ->get_data()
                     .data();
         } else {
-            return 
reinterpret_cast<ColumnUInt8*>(column->assume_mutable().get())
-                    ->get_data()
-                    .data();
+            return 
assert_cast<ColumnUInt8*>(column->assume_mutable().get())->get_data().data();
         }
     }
 
     uint8* _get_null_map(ColumnPtr column) const {
         if (column->is_nullable()) {
-            return reinterpret_cast<ColumnUInt8*>(
-                           
reinterpret_cast<ColumnNullable*>(column->assume_mutable().get())
+            return assert_cast<ColumnUInt8*>(
+                           
assert_cast<ColumnNullable*>(column->assume_mutable().get())
                                    ->get_null_map_column_ptr()
                                    .get())
                     ->get_data()
diff --git a/regression-test/data/query_p0/sql_functions/test_predicate.out 
b/regression-test/data/query_p0/sql_functions/test_predicate.out
new file mode 100644
index 0000000000..77dfc15c6e
--- /dev/null
+++ b/regression-test/data/query_p0/sql_functions/test_predicate.out
@@ -0,0 +1,48 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !null_or_null --
+
+-- !true_or_null --
+1      2       3       \N
+
+-- !null_or_true --
+1      2       3       \N
+
+-- !false_or_null --
+
+-- !null_or_false --
+
+-- !false_or_true --
+1      2       3       \N
+
+-- !true_or_false --
+1      2       3       \N
+
+-- !null_and_null --
+
+-- !true_and_null --
+
+-- !null_and_true --
+
+-- !false_and_null --
+
+-- !null_and_false --
+
+-- !false_and_true --
+
+-- !true_and_false --
+
+-- !not_false --
+1      2       3       \N
+
+-- !not_null --
+
+-- !false_is_null --
+
+-- !null_is_null --
+1      2       3       \N
+
+-- !false_eq_false --
+1      2       3       \N
+
+-- !null_eq_false --
+
diff --git 
a/regression-test/suites/query_p0/sql_functions/test_predicate.groovy 
b/regression-test/suites/query_p0/sql_functions/test_predicate.groovy
new file mode 100644
index 0000000000..20b3c179ad
--- /dev/null
+++ b/regression-test/suites/query_p0/sql_functions/test_predicate.groovy
@@ -0,0 +1,57 @@
+// 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("test_predicate") {
+    sql """drop table if exists t1;"""
+    sql """
+            create table t1 (
+                k1 int null,
+                k2 int null,
+                k3 int null,
+                k4 int null
+            )
+            duplicate key (k1)
+            distributed BY hash(k1) buckets 3
+            properties("replication_num" = "1");
+        """
+    sql """ insert into t1 values(1,2,3,null); """
+
+    qt_null_or_null "select * from t1 where abs(k1)=null or abs(k1)=null;"
+    qt_true_or_null "select * from t1 where abs(k1)=1 or abs(k1)=null;"
+    qt_null_or_true "select * from t1 where abs(k1)=null or abs(k1)=1;"
+    qt_false_or_null "select * from t1 where abs(k1)!=1 or abs(k1)=null;"
+    qt_null_or_false "select * from t1 where abs(k1)=null or abs(k1)!=1;"
+    qt_false_or_true "select * from t1 where abs(k1)!=1 or abs(k1)=1;"
+    qt_true_or_false "select * from t1 where abs(k1)=1 or abs(k1)!=1;"
+
+    qt_null_and_null "select * from t1 where abs(k1)=null and abs(k1)=null;"
+    qt_true_and_null "select * from t1 where abs(k1)=1 and abs(k1)=null;"
+    qt_null_and_true "select * from t1 where abs(k1)=null and abs(k1)=1;"
+    qt_false_and_null "select * from t1 where abs(k1)!=1 and abs(k1)=null;"
+    qt_null_and_false "select * from t1 where abs(k1)!=null and abs(k1)=1;"
+    qt_false_and_true "select * from t1 where abs(k1)!=1 and abs(k1)=1;"
+    qt_true_and_false "select * from t1 where abs(k1)=1 and abs(k1)!=1;"
+
+    qt_not_false "select * from t1 where not (abs(k1)!=1);"
+    qt_not_null "select * from t1 where not (abs(k1)!=1 or null);"
+
+    qt_false_is_null "select * from t1 where (abs(k1)!=1) is null;"
+    qt_null_is_null "select * from t1 where (abs(k1)!=1 or null) is null;"
+
+    qt_false_eq_false "select * from t1 where (abs(k1)!=1)=false;"
+    qt_null_eq_false "select * from t1 where (abs(k1)!=1 or null)=false;"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to