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 b95cd7eca2 [Refactor](function) Reconstruct default logic for const 
args. (#17830)
b95cd7eca2 is described below

commit b95cd7eca2e67ec62fb96b670754daf56fa2f336
Author: ZhaoChangle <zhaochan...@selectdb.com>
AuthorDate: Fri Mar 17 11:13:13 2023 +0800

    [Refactor](function) Reconstruct default logic for const args. (#17830)
---
 be/src/vec/functions/date_time_transforms.h        | 12 ++--
 be/src/vec/functions/function.cpp                  | 77 ++++++++++------------
 be/src/vec/functions/function.h                    |  6 +-
 .../functions/function_datetime_string_to_string.h | 21 +++---
 be/src/vec/functions/function_string.h             |  1 +
 be/src/vec/functions/round.h                       | 17 +++--
 6 files changed, 63 insertions(+), 71 deletions(-)

diff --git a/be/src/vec/functions/date_time_transforms.h 
b/be/src/vec/functions/date_time_transforms.h
index 0f70d446ff..94ee40221c 100644
--- a/be/src/vec/functions/date_time_transforms.h
+++ b/be/src/vec/functions/date_time_transforms.h
@@ -280,12 +280,12 @@ template <typename Transform>
 struct TransformerToStringTwoArgument {
     static void vector_constant(FunctionContext* context,
                                 const PaddedPODArray<typename 
Transform::FromType>& ts,
-                                const std::string& format, 
ColumnString::Chars& res_data,
+                                const StringRef& format, ColumnString::Chars& 
res_data,
                                 ColumnString::Offsets& res_offsets,
                                 PaddedPODArray<UInt8>& null_map) {
         auto len = ts.size();
         res_offsets.resize(len);
-        res_data.reserve(len * format.size() + len);
+        res_data.reserve(len * format.size + len);
         null_map.resize_fill(len, false);
 
         size_t offset = 0;
@@ -294,12 +294,10 @@ struct TransformerToStringTwoArgument {
             size_t new_offset;
             bool is_null;
             if constexpr (is_specialization_of_v<Transform, FromUnixTimeImpl>) 
{
-                std::tie(new_offset, is_null) =
-                        Transform::execute(t, StringRef(format.c_str(), 
format.size()), res_data,
-                                           offset, 
context->state()->timezone_obj());
-            } else {
                 std::tie(new_offset, is_null) = Transform::execute(
-                        t, StringRef(format.c_str(), format.size()), res_data, 
offset);
+                        t, format, res_data, offset, 
context->state()->timezone_obj());
+            } else {
+                std::tie(new_offset, is_null) = Transform::execute(t, format, 
res_data, offset);
             }
             res_offsets[i] = new_offset;
             null_map[i] = is_null;
diff --git a/be/src/vec/functions/function.cpp 
b/be/src/vec/functions/function.cpp
index 91ab3f71ed..cdeff0678a 100644
--- a/be/src/vec/functions/function.cpp
+++ b/be/src/vec/functions/function.cpp
@@ -128,8 +128,8 @@ NullPresence get_null_presence(const Block& block, const 
ColumnNumbers& args) {
     return res;
 }
 
-bool allArgumentsAreConstants(const Block& block, const ColumnNumbers& args) {
-    for (auto arg : args) {
+bool all_arguments_are_constant(const Block& block, const ColumnNumbers& args) 
{
+    for (const auto& arg : args) {
         if (!is_column_const(*block.get_by_position(arg).column)) {
             return false;
         }
@@ -138,53 +138,51 @@ bool allArgumentsAreConstants(const Block& block, const 
ColumnNumbers& args) {
 }
 } // namespace
 
+inline Status PreparedFunctionImpl::_execute_skipped_constant_deal(
+        FunctionContext* context, Block& block, const ColumnNumbers& args, 
size_t result,
+        size_t input_rows_count, bool dry_run) {
+    bool executed = false;
+    RETURN_IF_ERROR(default_implementation_for_nulls(context, block, args, 
result, input_rows_count,
+                                                     dry_run, &executed));
+    if (executed) {
+        return Status::OK();
+    }
+
+    if (dry_run) {
+        return execute_impl_dry_run(context, block, args, result, 
input_rows_count);
+    } else {
+        return execute_impl(context, block, args, result, input_rows_count);
+    }
+}
+
 Status PreparedFunctionImpl::default_implementation_for_constant_arguments(
         FunctionContext* context, Block& block, const ColumnNumbers& args, 
size_t result,
         size_t input_rows_count, bool dry_run, bool* executed) {
     *executed = false;
-    ColumnNumbers arguments_to_remain_constants = 
get_arguments_that_are_always_constant();
+    ColumnNumbers args_expect_const = get_arguments_that_are_always_constant();
 
-    /// Check that these arguments are really constant.
-    for (auto arg_num : arguments_to_remain_constants) {
+    // Check that these arguments are really constant.
+    for (auto arg_num : args_expect_const) {
         if (arg_num < args.size() &&
             !is_column_const(*block.get_by_position(args[arg_num]).column)) {
-            return Status::RuntimeError("Argument at index {} for function {}  
must be constant",
-                                        arg_num, get_name());
+            return Status::InvalidArgument("Argument at index {} for function 
{} must be constant",
+                                           arg_num, get_name());
         }
     }
 
     if (args.empty() || !use_default_implementation_for_constants() ||
-        !allArgumentsAreConstants(block, args)) {
+        !all_arguments_are_constant(block, args)) {
         return Status::OK();
     }
-
+    // now all columns is const.
     Block temporary_block;
-    bool have_converted_columns = false;
 
     size_t arguments_size = args.size();
     for (size_t arg_num = 0; arg_num < arguments_size; ++arg_num) {
         const ColumnWithTypeAndName& column = 
block.get_by_position(args[arg_num]);
-
-        if (arguments_to_remain_constants.end() != 
std::find(arguments_to_remain_constants.begin(),
-                                                             
arguments_to_remain_constants.end(),
-                                                             arg_num)) {
-            temporary_block.insert({column.column->clone_resized(1), 
column.type, column.name});
-        } else {
-            have_converted_columns = true;
-            temporary_block.insert(
-                    {assert_cast<const 
ColumnConst*>(column.column.get())->get_data_column_ptr(),
-                     column.type, column.name});
-        }
-    }
-
-    /** When using default implementation for constants, the function requires 
at least one argument
-      *  not in "arguments_to_remain_constants" set. Otherwise we get infinite 
recursion.
-      */
-    if (!have_converted_columns) {
-        return Status::RuntimeError(
-                "Number of arguments for function {} doesn't match: the 
function "
-                "requires more arguments",
-                get_name());
+        temporary_block.insert(
+                {assert_cast<const 
ColumnConst*>(column.column.get())->get_data_column_ptr(),
+                 column.type, column.name});
     }
 
     temporary_block.insert(block.get_by_position(result));
@@ -194,9 +192,9 @@ Status 
PreparedFunctionImpl::default_implementation_for_constant_arguments(
         temporary_argument_numbers[i] = i;
     }
 
-    RETURN_IF_ERROR(execute_without_low_cardinality_columns(
-            context, temporary_block, temporary_argument_numbers, 
arguments_size,
-            temporary_block.rows(), dry_run));
+    RETURN_IF_ERROR(_execute_skipped_constant_deal(context, temporary_block,
+                                                   temporary_argument_numbers, 
arguments_size,
+                                                   temporary_block.rows(), 
dry_run));
 
     ColumnPtr result_column;
     /// extremely rare case, when we have function with completely const 
arguments
@@ -248,21 +246,14 @@ Status 
PreparedFunctionImpl::execute_without_low_cardinality_columns(
         FunctionContext* context, Block& block, const ColumnNumbers& args, 
size_t result,
         size_t input_rows_count, bool dry_run) {
     bool executed = false;
+
     RETURN_IF_ERROR(default_implementation_for_constant_arguments(
             context, block, args, result, input_rows_count, dry_run, 
&executed));
     if (executed) {
         return Status::OK();
     }
-    RETURN_IF_ERROR(default_implementation_for_nulls(context, block, args, 
result, input_rows_count,
-                                                     dry_run, &executed));
-    if (executed) {
-        return Status::OK();
-    }
 
-    if (dry_run)
-        return execute_impl_dry_run(context, block, args, result, 
input_rows_count);
-    else
-        return execute_impl(context, block, args, result, input_rows_count);
+    return _execute_skipped_constant_deal(context, block, args, result, 
input_rows_count, dry_run);
 }
 
 Status PreparedFunctionImpl::execute(FunctionContext* context, Block& block,
diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h
index a002e90760..5af021656d 100644
--- a/be/src/vec/functions/function.h
+++ b/be/src/vec/functions/function.h
@@ -90,7 +90,7 @@ protected:
 
     /** If the function have non-zero number of arguments,
       *  and if all arguments are constant, that we could automatically 
provide default implementation:
-      *  arguments are converted to ordinary columns with single value, then 
function is executed as usual,
+      *  arguments are converted to ordinary columns with single value which 
is not const, then function is executed as usual,
       *  and then the result is converted to constant column.
       */
     virtual bool use_default_implementation_for_constants() const { return 
false; }
@@ -102,6 +102,7 @@ protected:
     virtual bool use_default_implementation_for_low_cardinality_columns() 
const { return true; }
 
     /** Some arguments could remain constant during this implementation.
+      * Every argument required const must write here and no checks elsewhere.
       */
     virtual ColumnNumbers get_arguments_that_are_always_constant() const { 
return {}; }
 
@@ -116,6 +117,9 @@ private:
     Status execute_without_low_cardinality_columns(FunctionContext* context, 
Block& block,
                                                    const ColumnNumbers& 
arguments, size_t result,
                                                    size_t input_rows_count, 
bool dry_run);
+    Status _execute_skipped_constant_deal(FunctionContext* context, Block& 
block,
+                                          const ColumnNumbers& args, size_t 
result,
+                                          size_t input_rows_count, bool 
dry_run);
 };
 
 /// Function with known arguments and return type.
diff --git a/be/src/vec/functions/function_datetime_string_to_string.h 
b/be/src/vec/functions/function_datetime_string_to_string.h
index 3e14c38ef4..a5cde61268 100644
--- a/be/src/vec/functions/function_datetime_string_to_string.h
+++ b/be/src/vec/functions/function_datetime_string_to_string.h
@@ -20,6 +20,7 @@
 #include "vec/columns/column_const.h"
 #include "vec/columns/column_nullable.h"
 #include "vec/columns/columns_number.h"
+#include "vec/common/string_ref.h"
 #include "vec/data_types/data_type_date.h"
 #include "vec/data_types/data_type_date_time.h"
 #include "vec/data_types/data_type_nullable.h"
@@ -72,21 +73,15 @@ public:
 
             if (arguments.size() == 2) {
                 const IColumn& source_col1 = 
*block.get_by_position(arguments[1]).column;
-                if (const auto* delta_const_column =
-                            typeid_cast<const ColumnConst*>(&source_col1)) {
-                    TransformerToStringTwoArgument<Transform>::vector_constant(
-                            context, sources->get_data(),
-                            delta_const_column->get_field().get<String>(), 
col_res->get_chars(),
-                            col_res->get_offsets(), vec_null_map_to);
-                } else {
-                    return Status::InternalError(
-                            "Illegal column {} is not const {}",
-                            
block.get_by_position(arguments[1]).column->get_name(), name);
-                }
-            } else {
+                StringRef formatter =
+                        source_col1.get_data_at(0); // for both ColumnString 
or ColumnConst.
                 TransformerToStringTwoArgument<Transform>::vector_constant(
-                        context, sources->get_data(), "%Y-%m-%d %H:%i:%s", 
col_res->get_chars(),
+                        context, sources->get_data(), formatter, 
col_res->get_chars(),
                         col_res->get_offsets(), vec_null_map_to);
+            } else { //default argument
+                TransformerToStringTwoArgument<Transform>::vector_constant(
+                        context, sources->get_data(), StringRef("%Y-%m-%d 
%H:%i:%s"),
+                        col_res->get_chars(), col_res->get_offsets(), 
vec_null_map_to);
             }
 
             if (nullable_column) {
diff --git a/be/src/vec/functions/function_string.h 
b/be/src/vec/functions/function_string.h
index 4524c2f718..855f15a611 100644
--- a/be/src/vec/functions/function_string.h
+++ b/be/src/vec/functions/function_string.h
@@ -1762,6 +1762,7 @@ private:
         }
     }
 
+    //TODO: need to be rewrited in a more efficient way. compare BMH/KMP/...
     size_t split_str(size_t& pos, const StringRef str_ref, StringRef 
delimiter_ref) {
         size_t old_size = pos;
         size_t str_size = str_ref.size;
diff --git a/be/src/vec/functions/round.h b/be/src/vec/functions/round.h
index 456d6264a2..591c9e4387 100644
--- a/be/src/vec/functions/round.h
+++ b/be/src/vec/functions/round.h
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#include "vec/columns/column_const.h"
+#include "vec/columns/columns_number.h"
 #ifdef __SSE4_1__
 #include <smmintrin.h>
 #else
@@ -500,17 +502,18 @@ public:
 
     static Status get_scale_arg(const ColumnWithTypeAndName& arguments, Int16* 
scale) {
         const IColumn& scale_column = *arguments.column;
-        if (!is_column_const(scale_column)) {
-            return Status::InvalidArgument("2nd argument for function {} 
should be constant", name);
-        }
 
-        Field scale_field = assert_cast<const 
ColumnConst&>(scale_column).get_field();
+        Int32 scale64 = static_cast<const ColumnInt32*>(
+                                &(is_column_const(scale_column)
+                                          ? static_cast<const 
ColumnConst*>(&scale_column)
+                                                    ->get_data_column()
+                                          : scale_column))
+                                ->get_element(0);
 
-        Int64 scale64 = scale_field.get<Int64>();
         if (scale64 > std::numeric_limits<Int16>::max() ||
             scale64 < std::numeric_limits<Int16>::min()) {
-            return Status::InvalidArgument("Scale argument for function {} is 
too large: {}", name,
-                                           scale64);
+            return Status::InvalidArgument("Scale argument for function {} is 
out of bound: {}",
+                                           name, scale64);
         }
 
         *scale = scale64;


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

Reply via email to