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

lihaopeng 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 f800ba8f4c [Exec](opt) Optimize function call for const columns 
(#18212)
f800ba8f4c is described below

commit f800ba8f4c5998b0456928711d5d09844acf4d53
Author: zclllyybb <[email protected]>
AuthorDate: Fri Mar 31 11:36:21 2023 +0800

    [Exec](opt) Optimize function call for const columns (#18212)
---
 be/src/vec/columns/column.h                        |   1 +
 be/src/vec/columns/column_const.cpp                |  35 +++
 be/src/vec/columns/column_const.h                  |  29 +++
 be/src/vec/columns/column_nullable.cpp             |  11 +
 be/src/vec/columns/column_nullable.h               |   6 +-
 be/src/vec/common/sort/sorter.cpp                  |   3 +-
 be/src/vec/common/string_ref.cpp                   |  15 ++
 be/src/vec/common/string_ref.h                     |   8 +
 .../vec/functions/array/function_array_apply.cpp   |  10 +-
 be/src/vec/functions/function_bitmap.cpp           | 251 +++++++++++++++++----
 be/src/vec/functions/function_totype.h             |  23 +-
 be/src/vec/functions/least_greast.cpp              |  96 ++++----
 12 files changed, 387 insertions(+), 101 deletions(-)

diff --git a/be/src/vec/columns/column.h b/be/src/vec/columns/column.h
index b0de27bb6e..c7e9e6f1e1 100644
--- a/be/src/vec/columns/column.h
+++ b/be/src/vec/columns/column.h
@@ -215,6 +215,7 @@ public:
 
     /// Appends range of elements from other column with the same type.
     /// Could be used to concatenate columns.
+    /// TODO: we need `insert_range_from_const` for every column type.
     virtual void insert_range_from(const IColumn& src, size_t start, size_t 
length) = 0;
 
     /// Appends one element from other column with the same type multiple 
times.
diff --git a/be/src/vec/columns/column_const.cpp 
b/be/src/vec/columns/column_const.cpp
index 7b7fc4d753..96d0c013b1 100644
--- a/be/src/vec/columns/column_const.cpp
+++ b/be/src/vec/columns/column_const.cpp
@@ -20,6 +20,8 @@
 
 #include "vec/columns/column_const.h"
 
+#include <algorithm>
+#include <cstddef>
 #include <utility>
 
 #include "gutil/port.h"
@@ -209,4 +211,37 @@ std::pair<ColumnPtr, size_t> 
check_column_const_set_readability(const IColumn& c
     }
     return result;
 }
+
+std::pair<const ColumnPtr&, bool> unpack_if_const(const ColumnPtr& ptr) 
noexcept {
+    if (is_column_const(*ptr)) {
+        return std::make_pair(
+                std::cref(static_cast<const 
ColumnConst&>(*ptr).get_data_column_ptr()), true);
+    }
+    return std::make_pair(std::cref(ptr), false);
+}
+
+void default_preprocess_parameter_columns(ColumnPtr* columns, const bool* 
col_const,
+                                          const std::initializer_list<size_t>& 
parameters,
+                                          Block& block, const ColumnNumbers& 
arg_indexes) noexcept {
+    if (std::all_of(parameters.begin(), parameters.end(),
+                    [&](size_t const_index) -> bool { return 
col_const[const_index]; })) {
+        // only need to avoid expanding when all parameters are const
+        for (auto index : parameters) {
+            columns[index] = static_cast<const ColumnConst&>(
+                                     
*block.get_by_position(arg_indexes[index]).column)
+                                     .get_data_column_ptr();
+        }
+    } else {
+        // no need to avoid expanding for this rare situation
+        for (auto index : parameters) {
+            if (col_const[index]) {
+                columns[index] = static_cast<const ColumnConst&>(
+                                         
*block.get_by_position(arg_indexes[index]).column)
+                                         .convert_to_full_column();
+            } else {
+                columns[index] = 
block.get_by_position(arg_indexes[index]).column;
+            }
+        }
+    }
+}
 } // namespace doris::vectorized
diff --git a/be/src/vec/columns/column_const.h 
b/be/src/vec/columns/column_const.h
index 357f10dcee..3ab11d6768 100644
--- a/be/src/vec/columns/column_const.h
+++ b/be/src/vec/columns/column_const.h
@@ -21,11 +21,15 @@
 #pragma once
 
 #include <cstddef>
+#include <initializer_list>
+#include <type_traits>
 
 #include "vec/columns/column.h"
 #include "vec/columns/column_nullable.h"
 #include "vec/common/assert_cast.h"
 #include "vec/common/typeid_cast.h"
+#include "vec/core/block.h"
+#include "vec/core/column_numbers.h"
 #include "vec/core/field.h"
 
 namespace doris::vectorized {
@@ -234,4 +238,29 @@ public:
 */
 std::pair<ColumnPtr, size_t> check_column_const_set_readability(const IColumn& 
column,
                                                                 const size_t 
row_num) noexcept;
+
+/*
+ * @warning use this function sometimes cause performance problem in GCC.
+*/
+template <typename T, std::enable_if_t<std::is_integral_v<T>, T> = 0>
+T index_check_const(T arg, bool constancy) noexcept {
+    return constancy ? 0 : arg;
+}
+
+/*
+ * @return first : data_column_ptr for ColumnConst, itself otherwise.
+ *         second : whether it's ColumnConst.
+*/
+std::pair<const ColumnPtr&, bool> unpack_if_const(const ColumnPtr&) noexcept;
+
+/*
+ * For the functions that some columns of arguments are almost but not 
completely always const, we use this function to preprocessing its parameter 
columns
+ * (which are not data columns). When we have two or more columns which only 
provide parameter, use this to deal with corner case. So you can specialize you
+ * implementations for all const or all parameters const, without considering 
some of parameters are const.
+ 
+ * Do the transformation only for the columns whose arg_indexes in parameters.
+*/
+void default_preprocess_parameter_columns(ColumnPtr* columns, const bool* 
col_const,
+                                          const std::initializer_list<size_t>& 
parameters,
+                                          Block& block, const ColumnNumbers& 
arg_indexes) noexcept;
 } // namespace doris::vectorized
diff --git a/be/src/vec/columns/column_nullable.cpp 
b/be/src/vec/columns/column_nullable.cpp
index 92fb114a4e..64db3e6455 100644
--- a/be/src/vec/columns/column_nullable.cpp
+++ b/be/src/vec/columns/column_nullable.cpp
@@ -27,6 +27,7 @@
 #include "vec/common/nan_utils.h"
 #include "vec/common/typeid_cast.h"
 #include "vec/core/sort_block.h"
+#include "vec/utils/util.hpp"
 
 namespace doris::vectorized {
 
@@ -633,4 +634,14 @@ ColumnPtr ColumnNullable::index(const IColumn& indexes, 
size_t limit) const {
     return ColumnNullable::create(indexed_data, indexed_null_map);
 }
 
+void check_set_nullable(ColumnPtr& argument_column, 
ColumnVector<UInt8>::MutablePtr& null_map) {
+    if (auto* nullable = 
check_and_get_column<ColumnNullable>(*argument_column)) {
+        // Danger: Here must dispose the null map data first! Because
+        // argument_columns[i]=nullable->get_nested_column_ptr(); will release 
the mem
+        // of column nullable mem of null map
+        VectorizedUtils::update_null_map(null_map->get_data(), 
nullable->get_null_map_data());
+        argument_column = nullable->get_nested_column_ptr();
+    }
+}
+
 } // namespace doris::vectorized
diff --git a/be/src/vec/columns/column_nullable.h 
b/be/src/vec/columns/column_nullable.h
index 0610b139eb..05b0516cda 100644
--- a/be/src/vec/columns/column_nullable.h
+++ b/be/src/vec/columns/column_nullable.h
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#include "vec/columns/column_vector.h"
+#include "vec/core/types.h"
 #ifdef __aarch64__
 #include <sse2neon.h>
 #endif
@@ -368,5 +370,7 @@ private:
 
 ColumnPtr make_nullable(const ColumnPtr& column, bool is_nullable = false);
 ColumnPtr remove_nullable(const ColumnPtr& column);
-
+// check if argument column is nullable. If so, extract its concrete column 
and set null_map.
+//TODO: use this to replace inner usages.
+void check_set_nullable(ColumnPtr&, ColumnVector<UInt8>::MutablePtr&);
 } // namespace doris::vectorized
diff --git a/be/src/vec/common/sort/sorter.cpp 
b/be/src/vec/common/sort/sorter.cpp
index c8eebed652..b5315a1489 100644
--- a/be/src/vec/common/sort/sorter.cpp
+++ b/be/src/vec/common/sort/sorter.cpp
@@ -306,8 +306,9 @@ Status FullSorter::append_block(Block* block) {
                     << " type1: " << data[i].type->get_name()
                     << " type2: " << arrival_data[i].type->get_name();
             try {
+                //TODO: to eliminate unnecessary expansion, we need a 
`insert_range_from_const` for every column type.
                 
RETURN_IF_CATCH_BAD_ALLOC(data[i].column->assume_mutable()->insert_range_from(
-                        
*arrival_data[i].column->convert_to_full_column_if_const().get(), 0, sz));
+                        
*arrival_data[i].column->convert_to_full_column_if_const(), 0, sz));
             } catch (const doris::Exception& e) {
                 return Status::Error(e.code(), e.to_string());
             }
diff --git a/be/src/vec/common/string_ref.cpp b/be/src/vec/common/string_ref.cpp
index 20cfbad708..d292b8160f 100644
--- a/be/src/vec/common/string_ref.cpp
+++ b/be/src/vec/common/string_ref.cpp
@@ -20,6 +20,8 @@
 
 #include "string_ref.h"
 
+#include "common/compiler_util.h"
+
 namespace doris {
 
 StringRef StringRef::trim() const {
@@ -53,6 +55,19 @@ StringRef StringRef::max_string_val() {
     return StringRef((char*)(&StringRef::MAX_CHAR), 1);
 }
 
+bool StringRef::start_with(char ch) const {
+    if (UNLIKELY(size == 0)) {
+        return false;
+    }
+    return data[0] == ch;
+}
+bool StringRef::end_with(char ch) const {
+    if (UNLIKELY(size == 0)) {
+        return false;
+    }
+    return data[size - 1] == ch;
+}
+
 bool StringRef::start_with(const StringRef& search_string) const {
     DCHECK(size >= search_string.size);
     if (search_string.size == 0) {
diff --git a/be/src/vec/common/string_ref.h b/be/src/vec/common/string_ref.h
index 7561b33c3c..9ecb1cfcf0 100644
--- a/be/src/vec/common/string_ref.h
+++ b/be/src/vec/common/string_ref.h
@@ -225,6 +225,12 @@ struct StringRef {
 
     StringRef substring(int start_pos) const { return substring(start_pos, 
size - start_pos); }
 
+    const char* begin() const { return data; }
+    const char* end() const { return data + size; }
+    // there's no border check in functions below. That's same with STL.
+    char front() const { return *data; }
+    char back() const { return *(data + size - 1); }
+
     // Trims leading and trailing spaces.
     StringRef trim() const;
 
@@ -237,6 +243,8 @@ struct StringRef {
     static StringRef min_string_val();
     static StringRef max_string_val();
 
+    bool start_with(char) const;
+    bool end_with(char) const;
     bool start_with(const StringRef& search_string) const;
     bool end_with(const StringRef& search_string) const;
 
diff --git a/be/src/vec/functions/array/function_array_apply.cpp 
b/be/src/vec/functions/array/function_array_apply.cpp
index 723dfc143a..bb81f04fda 100644
--- a/be/src/vec/functions/array/function_array_apply.cpp
+++ b/be/src/vec/functions/array/function_array_apply.cpp
@@ -37,6 +37,7 @@ public:
     String get_name() const override { return name; }
 
     size_t get_number_of_arguments() const override { return 3; }
+    ColumnNumbers get_arguments_that_are_always_constant() const override { 
return {1, 2}; }
 
     DataTypePtr get_return_type_impl(const DataTypes& arguments) const 
override {
         DCHECK(is_array(arguments[0]))
@@ -63,10 +64,7 @@ public:
         auto nested_type = assert_cast<const 
DataTypeArray&>(*src_column_type).get_nested_type();
         const std::string& condition =
                 
block.get_by_position(arguments[1]).column->get_data_at(0).to_string();
-        if (!is_column_const(*block.get_by_position(arguments[2]).column)) {
-            return Status::RuntimeError(
-                    "execute failed or unsupported column, only support const 
column");
-        }
+
         const ColumnConst& rhs_value_column =
                 static_cast<const 
ColumnConst&>(*block.get_by_position(arguments[2]).column.get());
         ColumnPtr result_ptr;
@@ -137,7 +135,9 @@ private:
         size_t out_pos = 0;
         for (size_t i = 0; i < src_offsets.size(); ++i) {
             for (; in_pos < src_offsets[i]; ++in_pos) {
-                if (filter[in_pos]) ++out_pos;
+                if (filter[in_pos]) {
+                    ++out_pos;
+                }
             }
             dst_offsets[i] = out_pos;
         }
diff --git a/be/src/vec/functions/function_bitmap.cpp 
b/be/src/vec/functions/function_bitmap.cpp
index 01991f1b2f..d6cf1652db 100644
--- a/be/src/vec/functions/function_bitmap.cpp
+++ b/be/src/vec/functions/function_bitmap.cpp
@@ -444,13 +444,26 @@ struct BitmapNot {
     using T1 = typename RightDataType::FieldType;
     using TData = std::vector<BitmapValue>;
 
-    static Status vector_vector(const TData& lvec, const TData& rvec, TData& 
res) {
+    static void vector_vector(const TData& lvec, const TData& rvec, TData& 
res) {
         size_t size = lvec.size();
         for (size_t i = 0; i < size; ++i) {
             res[i] = lvec[i];
             res[i] -= rvec[i];
         }
-        return Status::OK();
+    }
+    static void vector_scalar(const TData& lvec, const BitmapValue& rval, 
TData& res) {
+        size_t size = lvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            res[i] = lvec[i];
+            res[i] -= rval;
+        }
+    }
+    static void scalar_vector(const BitmapValue& lval, const TData& rvec, 
TData& res) {
+        size_t size = rvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            res[i] = lval;
+            res[i] -= rvec[i];
+        }
     }
 };
 
@@ -465,7 +478,7 @@ struct BitmapAndNot {
     using T1 = typename RightDataType::FieldType;
     using TData = std::vector<BitmapValue>;
 
-    static Status vector_vector(const TData& lvec, const TData& rvec, TData& 
res) {
+    static void vector_vector(const TData& lvec, const TData& rvec, TData& 
res) {
         size_t size = lvec.size();
         BitmapValue mid_data;
         for (size_t i = 0; i < size; ++i) {
@@ -475,7 +488,28 @@ struct BitmapAndNot {
             res[i] -= mid_data;
             mid_data.clear();
         }
-        return Status::OK();
+    }
+    static void vector_scalar(const TData& lvec, const BitmapValue& rval, 
TData& res) {
+        size_t size = lvec.size();
+        BitmapValue mid_data;
+        for (size_t i = 0; i < size; ++i) {
+            mid_data = lvec[i];
+            mid_data &= rval;
+            res[i] = lvec[i];
+            res[i] -= mid_data;
+            mid_data.clear();
+        }
+    }
+    static void scalar_vector(const BitmapValue& lval, const TData& rvec, 
TData& res) {
+        size_t size = rvec.size();
+        BitmapValue mid_data;
+        for (size_t i = 0; i < size; ++i) {
+            mid_data = lval;
+            mid_data &= rvec[i];
+            res[i] = lval;
+            res[i] -= mid_data;
+            mid_data.clear();
+        }
     }
 };
 
@@ -491,7 +525,7 @@ struct BitmapAndNotCount {
     using TData = std::vector<BitmapValue>;
     using ResTData = typename ColumnVector<Int64>::Container::value_type;
 
-    static Status vector_vector(const TData& lvec, const TData& rvec, 
ResTData* res) {
+    static void vector_vector(const TData& lvec, const TData& rvec, ResTData* 
res) {
         size_t size = lvec.size();
         BitmapValue mid_data;
         for (size_t i = 0; i < size; ++i) {
@@ -500,7 +534,26 @@ struct BitmapAndNotCount {
             res[i] = lvec[i].andnot_cardinality(mid_data);
             mid_data.clear();
         }
-        return Status::OK();
+    }
+    static void scalar_vector(const BitmapValue& lval, const TData& rvec, 
ResTData* res) {
+        size_t size = rvec.size();
+        BitmapValue mid_data;
+        for (size_t i = 0; i < size; ++i) {
+            mid_data = lval;
+            mid_data &= rvec[i];
+            res[i] = lval.andnot_cardinality(mid_data);
+            mid_data.clear();
+        }
+    }
+    static void vector_scalar(const TData& lvec, const BitmapValue& rval, 
ResTData* res) {
+        size_t size = lvec.size();
+        BitmapValue mid_data;
+        for (size_t i = 0; i < size; ++i) {
+            mid_data = lvec[i];
+            mid_data &= rval;
+            res[i] = lvec[i].andnot_cardinality(mid_data);
+            mid_data.clear();
+        }
     }
 };
 
@@ -622,11 +675,6 @@ public:
     Status execute_impl_internal(FunctionContext* context, Block& block,
                                  const ColumnNumbers& arguments, size_t result,
                                  size_t input_rows_count) {
-        const auto& left = block.get_by_position(arguments[0]);
-        auto lcol = left.column->convert_to_full_column_if_const();
-        const auto& right = block.get_by_position(arguments[1]);
-        auto rcol = right.column->convert_to_full_column_if_const();
-
         using ResultType = typename ResultDataType::FieldType;
         using ColVecResult = ColumnVector<ResultType>;
 
@@ -634,10 +682,29 @@ public:
         auto& vec_res = col_res->get_data();
         vec_res.resize(block.rows());
 
-        const ColumnBitmap* l_bitmap_col = assert_cast<const 
ColumnBitmap*>(lcol.get());
-        const ColumnBitmap* r_bitmap_col = assert_cast<const 
ColumnBitmap*>(rcol.get());
-        BitmapAndNotCount<LeftDataType, RightDataType>::vector_vector(
-                l_bitmap_col->get_data(), r_bitmap_col->get_data(), 
vec_res.data());
+        const auto& left = block.get_by_position(arguments[0]);
+        auto lcol = left.column;
+        const auto& right = block.get_by_position(arguments[1]);
+        auto rcol = right.column;
+
+        if (is_column_const(*left.column)) {
+            BitmapAndNotCount<LeftDataType, RightDataType>::scalar_vector(
+                    assert_cast<const ColumnBitmap&>(
+                            assert_cast<const 
ColumnConst*>(lcol.get())->get_data_column())
+                            .get_data()[0],
+                    assert_cast<const ColumnBitmap*>(rcol.get())->get_data(), 
vec_res.data());
+        } else if (is_column_const(*right.column)) {
+            BitmapAndNotCount<LeftDataType, RightDataType>::vector_scalar(
+                    assert_cast<const ColumnBitmap*>(lcol.get())->get_data(),
+                    assert_cast<const ColumnBitmap&>(
+                            assert_cast<const 
ColumnConst*>(rcol.get())->get_data_column())
+                            .get_data()[0],
+                    vec_res.data());
+        } else {
+            BitmapAndNotCount<LeftDataType, RightDataType>::vector_vector(
+                    assert_cast<const ColumnBitmap*>(lcol.get())->get_data(),
+                    assert_cast<const ColumnBitmap*>(rcol.get())->get_data(), 
vec_res.data());
+        }
 
         auto& result_info = block.get_by_position(result);
         if (result_info.type->is_nullable()) {
@@ -664,12 +731,23 @@ struct BitmapContains {
     using RTData = typename ColumnVector<T1>::Container;
     using ResTData = typename ColumnVector<UInt8>::Container;
 
-    static Status vector_vector(const LTData& lvec, const RTData& rvec, 
ResTData& res) {
+    static void vector_vector(const LTData& lvec, const RTData& rvec, 
ResTData& res) {
         size_t size = lvec.size();
         for (size_t i = 0; i < size; ++i) {
             res[i] = lvec[i].contains(rvec[i]);
         }
-        return Status::OK();
+    }
+    static void vector_scalar(const LTData& lvec, const T1& rval, ResTData& 
res) {
+        size_t size = lvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            res[i] = lvec[i].contains(rval);
+        }
+    }
+    static void scalar_vector(const BitmapValue& lval, const RTData& rvec, 
ResTData& res) {
+        size_t size = rvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            res[i] = lval.contains(rvec[i]);
+        }
     }
 };
 
@@ -685,14 +763,29 @@ struct BitmapHasAny {
     using TData = std::vector<BitmapValue>;
     using ResTData = typename ColumnVector<UInt8>::Container;
 
-    static Status vector_vector(const TData& lvec, const TData& rvec, 
ResTData& res) {
+    static void vector_vector(const TData& lvec, const TData& rvec, ResTData& 
res) {
         size_t size = lvec.size();
         for (size_t i = 0; i < size; ++i) {
             auto bitmap = const_cast<BitmapValue&>(lvec[i]);
             bitmap &= rvec[i];
             res[i] = bitmap.cardinality() != 0;
         }
-        return Status::OK();
+    }
+    static void vector_scalar(const TData& lvec, const BitmapValue& rval, 
ResTData& res) {
+        size_t size = lvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            auto bitmap = const_cast<BitmapValue&>(lvec[i]);
+            bitmap &= rval;
+            res[i] = bitmap.cardinality() != 0;
+        }
+    }
+    static void scalar_vector(const BitmapValue& lval, const TData& rvec, 
ResTData& res) {
+        size_t size = rvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            auto bitmap = const_cast<BitmapValue&>(lval);
+            bitmap &= rvec[i];
+            res[i] = bitmap.cardinality() != 0;
+        }
     }
 };
 
@@ -708,7 +801,7 @@ struct BitmapHasAll {
     using TData = std::vector<BitmapValue>;
     using ResTData = typename ColumnVector<UInt8>::Container;
 
-    static Status vector_vector(const TData& lvec, const TData& rvec, 
ResTData& res) {
+    static void vector_vector(const TData& lvec, const TData& rvec, ResTData& 
res) {
         size_t size = lvec.size();
         for (size_t i = 0; i < size; ++i) {
             uint64_t lhs_cardinality = lvec[i].cardinality();
@@ -716,7 +809,24 @@ struct BitmapHasAll {
             bitmap |= rvec[i];
             res[i] = bitmap.cardinality() == lhs_cardinality;
         }
-        return Status::OK();
+    }
+    static void vector_scalar(const TData& lvec, const BitmapValue& rval, 
ResTData& res) {
+        size_t size = lvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            uint64_t lhs_cardinality = lvec[i].cardinality();
+            auto bitmap = const_cast<BitmapValue&>(lvec[i]);
+            bitmap |= rval;
+            res[i] = bitmap.cardinality() == lhs_cardinality;
+        }
+    }
+    static void scalar_vector(const BitmapValue& lval, const TData& rvec, 
ResTData& res) {
+        size_t size = rvec.size();
+        for (size_t i = 0; i < size; ++i) {
+            uint64_t lhs_cardinality = lval.cardinality();
+            auto bitmap = const_cast<BitmapValue&>(lval);
+            bitmap |= rvec[i];
+            res[i] = bitmap.cardinality() == lhs_cardinality;
+        }
     }
 };
 
@@ -748,9 +858,9 @@ struct SubBitmap {
     using TData1 = std::vector<BitmapValue>;
     using TData2 = typename ColumnVector<Int64>::Container;
 
-    static Status vector_vector(const TData1& bitmap_data, const TData2& 
offset_data,
-                                const TData2& limit_data, NullMap& null_map,
-                                size_t input_rows_count, TData1& res) {
+    static void vector3(const TData1& bitmap_data, const TData2& offset_data,
+                        const TData2& limit_data, NullMap& null_map, size_t 
input_rows_count,
+                        TData1& res) {
         for (int i = 0; i < input_rows_count; ++i) {
             if (null_map[i]) {
                 continue;
@@ -764,7 +874,23 @@ struct SubBitmap {
                 null_map[i] = 1;
             }
         }
-        return Status::OK();
+    }
+    static void vector_scalars(const TData1& bitmap_data, const Int64& 
offset_data,
+                               const Int64& limit_data, NullMap& null_map, 
size_t input_rows_count,
+                               TData1& res) {
+        for (int i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                continue;
+            }
+            if (limit_data <= 0) {
+                null_map[i] = 1;
+                continue;
+            }
+            if (const_cast<TData1&>(bitmap_data)[i].offset_limit(offset_data, 
limit_data,
+                                                                 &res[i]) == 
0) {
+                null_map[i] = 1;
+            }
+        }
     }
 };
 
@@ -773,9 +899,9 @@ struct BitmapSubsetLimit {
     using TData1 = std::vector<BitmapValue>;
     using TData2 = typename ColumnVector<Int64>::Container;
 
-    static Status vector_vector(const TData1& bitmap_data, const TData2& 
offset_data,
-                                const TData2& limit_data, NullMap& null_map,
-                                size_t input_rows_count, TData1& res) {
+    static void vector3(const TData1& bitmap_data, const TData2& offset_data,
+                        const TData2& limit_data, NullMap& null_map, size_t 
input_rows_count,
+                        TData1& res) {
         for (int i = 0; i < input_rows_count; ++i) {
             if (null_map[i]) {
                 continue;
@@ -786,7 +912,20 @@ struct BitmapSubsetLimit {
             }
             const_cast<TData1&>(bitmap_data)[i].sub_limit(offset_data[i], 
limit_data[i], &res[i]);
         }
-        return Status::OK();
+    }
+    static void vector_scalars(const TData1& bitmap_data, const Int64& 
offset_data,
+                               const Int64& limit_data, NullMap& null_map, 
size_t input_rows_count,
+                               TData1& res) {
+        for (int i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                continue;
+            }
+            if (offset_data < 0 || limit_data < 0) {
+                null_map[i] = 1;
+                continue;
+            }
+            const_cast<TData1&>(bitmap_data)[i].sub_limit(offset_data, 
limit_data, &res[i]);
+        }
     }
 };
 
@@ -795,9 +934,9 @@ struct BitmapSubsetInRange {
     using TData1 = std::vector<BitmapValue>;
     using TData2 = typename ColumnVector<Int64>::Container;
 
-    static Status vector_vector(const TData1& bitmap_data, const TData2& 
range_start,
-                                const TData2& range_end, NullMap& null_map, 
size_t input_rows_count,
-                                TData1& res) {
+    static void vector3(const TData1& bitmap_data, const TData2& range_start,
+                        const TData2& range_end, NullMap& null_map, size_t 
input_rows_count,
+                        TData1& res) {
         for (int i = 0; i < input_rows_count; ++i) {
             if (null_map[i]) {
                 continue;
@@ -808,7 +947,20 @@ struct BitmapSubsetInRange {
             }
             const_cast<TData1&>(bitmap_data)[i].sub_range(range_start[i], 
range_end[i], &res[i]);
         }
-        return Status::OK();
+    }
+    static void vector_scalars(const TData1& bitmap_data, const Int64& 
range_start,
+                               const Int64& range_end, NullMap& null_map, 
size_t input_rows_count,
+                               TData1& res) {
+        for (int i = 0; i < input_rows_count; ++i) {
+            if (null_map[i]) {
+                continue;
+            }
+            if (range_start >= range_end || range_start < 0 || range_end < 0) {
+                null_map[i] = 1;
+                continue;
+            }
+            const_cast<TData1&>(bitmap_data)[i].sub_range(range_start, 
range_end, &res[i]);
+        }
     }
 };
 
@@ -835,25 +987,36 @@ public:
         DCHECK_EQ(arguments.size(), 3);
         auto res_null_map = ColumnUInt8::create(input_rows_count, 0);
         auto res_data_column = ColumnBitmap::create(input_rows_count);
-        ColumnPtr argument_columns[3];
 
+        bool col_const[3];
+        ColumnPtr argument_columns[3];
         for (int i = 0; i < 3; ++i) {
-            argument_columns[i] =
-                    
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const();
-            if (auto* nullable = 
check_and_get_column<ColumnNullable>(*argument_columns[i])) {
-                VectorizedUtils::update_null_map(res_null_map->get_data(),
-                                                 
nullable->get_null_map_data());
-                argument_columns[i] = nullable->get_nested_column_ptr();
-            }
+            col_const[i] = 
is_column_const(*block.get_by_position(arguments[i]).column);
+        }
+        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
+                                                     
*block.get_by_position(arguments[0]).column)
+                                                     .convert_to_full_column()
+                                           : 
block.get_by_position(arguments[0]).column;
+
+        default_preprocess_parameter_columns(argument_columns, col_const, {1, 
2}, block, arguments);
+
+        for (int i = 0; i < 3; i++) {
+            check_set_nullable(argument_columns[i], res_null_map);
         }
 
         auto bitmap_column = assert_cast<const 
ColumnBitmap*>(argument_columns[0].get());
         auto offset_column = assert_cast<const 
ColumnVector<Int64>*>(argument_columns[1].get());
         auto limit_column = assert_cast<const 
ColumnVector<Int64>*>(argument_columns[2].get());
 
-        Impl::vector_vector(bitmap_column->get_data(), 
offset_column->get_data(),
-                            limit_column->get_data(), 
res_null_map->get_data(), input_rows_count,
-                            res_data_column->get_data());
+        if (col_const[1] && col_const[2]) {
+            Impl::vector_scalars(bitmap_column->get_data(), 
offset_column->get_element(0),
+                                 limit_column->get_element(0), 
res_null_map->get_data(),
+                                 input_rows_count, 
res_data_column->get_data());
+        } else {
+            Impl::vector3(bitmap_column->get_data(), offset_column->get_data(),
+                          limit_column->get_data(), res_null_map->get_data(), 
input_rows_count,
+                          res_data_column->get_data());
+        }
 
         block.get_by_position(result).column =
                 ColumnNullable::create(std::move(res_data_column), 
std::move(res_null_map));
diff --git a/be/src/vec/functions/function_totype.h 
b/be/src/vec/functions/function_totype.h
index bc16e066f8..344223a024 100644
--- a/be/src/vec/functions/function_totype.h
+++ b/be/src/vec/functions/function_totype.h
@@ -19,6 +19,8 @@
 #include <fmt/format.h>
 
 #include "vec/columns/column_complex.h"
+#include "vec/columns/column_const.h"
+#include "vec/columns/column_nullable.h"
 #include "vec/columns/column_string.h"
 #include "vec/columns/column_vector.h"
 #include "vec/data_types/data_type.h"
@@ -143,10 +145,10 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
                         size_t result, size_t /*input_rows_count*/) override {
         DCHECK_EQ(arguments.size(), 2);
-        const auto& left = block.get_by_position(arguments[0]);
-        auto lcol = left.column->convert_to_full_column_if_const();
-        const auto& right = block.get_by_position(arguments[1]);
-        auto rcol = right.column->convert_to_full_column_if_const();
+        const auto& [lcol, left_const] =
+                unpack_if_const(block.get_by_position(arguments[0]).column);
+        const auto& [rcol, right_const] =
+                unpack_if_const(block.get_by_position(arguments[1]).column);
 
         using ResultDataType = typename Impl<LeftDataType, 
RightDataType>::ResultDataType;
 
@@ -171,8 +173,17 @@ public:
 
         if (auto col_left = check_and_get_column<ColVecLeft>(lcol.get())) {
             if (auto col_right = 
check_and_get_column<ColVecRight>(rcol.get())) {
-                Impl<LeftDataType, 
RightDataType>::vector_vector(col_left->get_data(),
-                                                                 
col_right->get_data(), vec_res);
+                if (left_const) {
+                    Impl<LeftDataType, RightDataType>::scalar_vector(
+                            col_left->get_data()[0], col_right->get_data(), 
vec_res);
+                } else if (right_const) {
+                    Impl<LeftDataType, RightDataType>::vector_scalar(
+                            col_left->get_data(), col_right->get_data()[0], 
vec_res);
+                } else {
+                    Impl<LeftDataType, RightDataType>::vector_vector(
+                            col_left->get_data(), col_right->get_data(), 
vec_res);
+                }
+
                 block.replace_by_position(result, std::move(col_res));
                 return Status::OK();
             }
diff --git a/be/src/vec/functions/least_greast.cpp 
b/be/src/vec/functions/least_greast.cpp
index 072ba8cbd5..5125f9a5b6 100644
--- a/be/src/vec/functions/least_greast.cpp
+++ b/be/src/vec/functions/least_greast.cpp
@@ -15,8 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include "vec/columns/column_const.h"
 #include "vec/columns/column_vector.h"
 #include "vec/columns/columns_number.h"
+#include "vec/common/assert_cast.h"
 #include "vec/core/accurate_comparison.h"
 #include "vec/data_types/data_type.h"
 #include "vec/data_types/data_type_number.h"
@@ -34,60 +36,33 @@ struct CompareMultiImpl {
 
     static DataTypePtr get_return_type_impl(const DataTypes& arguments) { 
return arguments[0]; }
 
-    template <typename ColumnType>
-    static void insert_result_data(MutableColumnPtr& result_column, ColumnPtr& 
argument_column,
-                                   const size_t input_rows_count) {
-        auto* __restrict result_raw_data =
-                
reinterpret_cast<ColumnType*>(result_column.get())->get_data().data();
-        auto* __restrict column_raw_data =
-                reinterpret_cast<const 
ColumnType*>(argument_column.get())->get_data().data();
-
-        if constexpr (std::is_same_v<ColumnType, ColumnDecimal128>) {
-            for (size_t i = 0; i < input_rows_count; ++i) {
-                result_raw_data[i] = Op<DecimalV2Value, 
DecimalV2Value>::apply(column_raw_data[i],
-                                                                               
result_raw_data[i])
-                                             ? column_raw_data[i]
-                                             : result_raw_data[i];
-            }
-        } else {
-            for (size_t i = 0; i < input_rows_count; ++i) {
-                using type = std::decay_t<decltype(result_raw_data[0])>;
-                result_raw_data[i] = Op<type, type>::apply(column_raw_data[i], 
result_raw_data[i])
-                                             ? column_raw_data[i]
-                                             : result_raw_data[i];
-            }
-        }
-    }
-
     static ColumnPtr execute(Block& block, const ColumnNumbers& arguments,
                              size_t input_rows_count) {
-        if (arguments.size() == 1) return 
block.get_by_position(arguments.back()).column;
+        if (arguments.size() == 1) {
+            return block.get_by_position(arguments.back()).column;
+        }
 
         const auto& data_type = block.get_by_position(arguments.back()).type;
         MutableColumnPtr result_column = data_type->create_column();
 
-        Columns args;
+        Columns cols(arguments.size());
+        std::unique_ptr<bool[]> col_const = 
std::make_unique<bool[]>(arguments.size());
         for (int i = 0; i < arguments.size(); ++i) {
-            args.emplace_back(
-                    
block.get_by_position(arguments[i]).column->convert_to_full_column_if_const());
+            std::tie(cols[i], col_const[i]) =
+                    
unpack_if_const(block.get_by_position(arguments[i]).column);
         }
         // because now the string types does not support random position 
writing,
         // so insert into result data have two methods, one is for string 
types, one is for others type remaining
-        bool is_string_result = result_column->is_column_string();
-        if (is_string_result) {
+        if (result_column->is_column_string()) {
             result_column->reserve(input_rows_count);
-        } else {
-            result_column->insert_range_from(*(args[0]), 0, input_rows_count);
-        }
-
-        if (is_string_result) {
-            const auto& column_string = reinterpret_cast<const 
ColumnString&>(*args[0]);
+            const auto& column_string = reinterpret_cast<const 
ColumnString&>(*cols[0]);
             auto& column_res = reinterpret_cast<ColumnString&>(*result_column);
 
             for (int i = 0; i < input_rows_count; ++i) {
                 auto str_data = column_string.get_data_at(i);
-                for (int j = 1; j < arguments.size(); ++j) {
-                    auto temp_data = reinterpret_cast<const 
ColumnString&>(*args[j]).get_data_at(i);
+                for (int cmp_col = 1; cmp_col < arguments.size(); ++cmp_col) {
+                    auto temp_data = assert_cast<const 
ColumnString&>(*cols[cmp_col])
+                                             .get_data_at(index_check_const(i, 
col_const[i]));
                     str_data = Op<StringRef, StringRef>::apply(temp_data, 
str_data) ? temp_data
                                                                                
     : str_data;
                 }
@@ -95,12 +70,15 @@ struct CompareMultiImpl {
             }
 
         } else {
+            result_column->insert_range_from(*(cols[0]), 0, input_rows_count);
             WhichDataType which(data_type);
-#define DISPATCH(TYPE, COLUMN_TYPE)                                            
        \
-    if (which.idx == TypeIndex::TYPE) {                                        
        \
-        for (int i = 1; i < arguments.size(); ++i) {                           
        \
-            insert_result_data<COLUMN_TYPE>(result_column, args[i], 
input_rows_count); \
-        }                                                                      
        \
+
+#define DISPATCH(TYPE, COLUMN_TYPE)                                            
       \
+    if (which.idx == TypeIndex::TYPE) {                                        
       \
+        for (int i = 1; i < arguments.size(); ++i) {                           
       \
+            insert_result_data<COLUMN_TYPE>(result_column, cols[i], 
input_rows_count, \
+                                            col_const[i]);                     
       \
+        }                                                                      
       \
     }
             NUMERIC_TYPE_TO_COLUMN_TYPE(DISPATCH)
             DISPATCH(Decimal128, ColumnDecimal<Decimal128>)
@@ -110,6 +88,36 @@ struct CompareMultiImpl {
 
         return result_column;
     }
+
+private:
+    template <typename ColumnType>
+    static void insert_result_data(const MutableColumnPtr& result_column,
+                                   const ColumnPtr& argument_column, const 
size_t input_rows_count,
+                                   const bool arg_const) {
+        auto* __restrict result_raw_data =
+                
reinterpret_cast<ColumnType*>(result_column.get())->get_data().data();
+        auto* __restrict column_raw_data =
+                reinterpret_cast<const 
ColumnType*>(argument_column.get())->get_data().data();
+
+        if constexpr (std::is_same_v<ColumnType, ColumnDecimal128>) {
+            for (size_t i = 0; i < input_rows_count; ++i) {
+                result_raw_data[i] = Op<DecimalV2Value, DecimalV2Value>::apply(
+                                             
column_raw_data[index_check_const(i, arg_const)],
+                                             result_raw_data[i])
+                                             ? 
column_raw_data[index_check_const(i, arg_const)]
+                                             : result_raw_data[i];
+            }
+        } else {
+            for (size_t i = 0; i < input_rows_count; ++i) {
+                using type = std::decay_t<decltype(result_raw_data[0])>;
+                result_raw_data[i] =
+                        Op<type, 
type>::apply(column_raw_data[index_check_const(i, arg_const)],
+                                              result_raw_data[i])
+                                ? column_raw_data[index_check_const(i, 
arg_const)]
+                                : result_raw_data[i];
+            }
+        }
+    }
 };
 
 struct FunctionFieldImpl {


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


Reply via email to