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

dataroaring pushed a commit to branch branch-3.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new e4f5f18ef4e branch-3.0: [fix](function) check return type is nullptr 
in FunctionBasePtr::build #49737 (#49762)
e4f5f18ef4e is described below

commit e4f5f18ef4e9aef137c1a80ebf5cc7d270754687
Author: Mryange <yanxuech...@selectdb.com>
AuthorDate: Wed Apr 9 09:47:26 2025 +0800

    branch-3.0: [fix](function) check return type is nullptr in 
FunctionBasePtr::build #49737 (#49762)
    
    https://github.com/apache/doris/pull/49737
---
 .../vec/functions/array/function_array_cum_sum.cpp | 10 +--
 .../functions/array/function_array_difference.h    |  8 +-
 .../vec/functions/array/function_array_element.h   |  6 +-
 .../array/function_array_enumerate_uniq.cpp        |  1 -
 be/src/vec/functions/function.h                    |  8 ++
 .../vec/function/simple_function_factory_test.cpp  | 98 ++++++++++++++++++++++
 6 files changed, 116 insertions(+), 15 deletions(-)

diff --git a/be/src/vec/functions/array/function_array_cum_sum.cpp 
b/be/src/vec/functions/array/function_array_cum_sum.cpp
index 24750b55f6c..73a87fd7cf2 100644
--- a/be/src/vec/functions/array/function_array_cum_sum.cpp
+++ b/be/src/vec/functions/array/function_array_cum_sum.cpp
@@ -86,14 +86,10 @@ public:
         }
         if (return_type) {
             return std::make_shared<DataTypeArray>(make_nullable(return_type));
-        } else {
-            throw doris::Exception(
-                    ErrorCode::INVALID_ARGUMENT,
-                    "Function of {}, return type get wrong: and input argument 
is: {}", name,
-                    arguments[0]->get_name());
         }
-
-        return nullptr;
+        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
+                               "Function of {}, return type get wrong: and 
input argument is: {}",
+                               name, arguments[0]->get_name());
     }
 
     Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
diff --git a/be/src/vec/functions/array/function_array_difference.h 
b/be/src/vec/functions/array/function_array_difference.h
index 9eca677f033..46cda52516a 100644
--- a/be/src/vec/functions/array/function_array_difference.h
+++ b/be/src/vec/functions/array/function_array_difference.h
@@ -95,12 +95,10 @@ public:
         if (return_type) {
             return std::make_shared<DataTypeArray>(is_nullable ? 
make_nullable(return_type)
                                                                : return_type);
-        } else {
-            throw doris::Exception(
-                    ErrorCode::INVALID_ARGUMENT,
-                    "Function of {}, return type get wrong: and input argument 
is: {}", name,
-                    arguments[0]->get_name());
         }
+        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
+                               "Function of {}, return type get wrong: and 
input argument is: {}",
+                               name, arguments[0]->get_name());
     }
 
     Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
diff --git a/be/src/vec/functions/array/function_array_element.h 
b/be/src/vec/functions/array/function_array_element.h
index b1a55e6f1a5..ea729e7be3f 100644
--- a/be/src/vec/functions/array/function_array_element.h
+++ b/be/src/vec/functions/array/function_array_element.h
@@ -90,8 +90,10 @@ public:
             return make_nullable(
                     
check_and_get_data_type<DataTypeMap>(arg_0.get())->get_value_type());
         } else {
-            LOG(ERROR) << "element_at only support array and map so far.";
-            return nullptr;
+            throw doris::Exception(
+                    ErrorCode::INVALID_ARGUMENT,
+                    fmt::format("element_at only support array and map so far, 
but got {}",
+                                arg_0->get_name()));
         }
     }
 
diff --git a/be/src/vec/functions/array/function_array_enumerate_uniq.cpp 
b/be/src/vec/functions/array/function_array_enumerate_uniq.cpp
index 4c073386e4d..bb9dd9c04cc 100644
--- a/be/src/vec/functions/array/function_array_enumerate_uniq.cpp
+++ b/be/src/vec/functions/array/function_array_enumerate_uniq.cpp
@@ -82,7 +82,6 @@ public:
             throw doris::Exception(
                     ErrorCode::INVALID_ARGUMENT,
                     "Incorrect number of arguments for array_enumerate_uniq 
function");
-            __builtin_unreachable();
         }
         bool is_nested_nullable = false;
         for (size_t i = 0; i < arguments.size(); ++i) {
diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h
index ff987d130cd..edc214e5f36 100644
--- a/be/src/vec/functions/function.h
+++ b/be/src/vec/functions/function.h
@@ -295,6 +295,14 @@ public:
     FunctionBasePtr build(const ColumnsWithTypeAndName& arguments,
                           const DataTypePtr& return_type) const final {
         const DataTypePtr& func_return_type = get_return_type(arguments);
+        if (func_return_type == nullptr) {
+            throw doris::Exception(
+                    ErrorCode::INTERNAL_ERROR,
+                    "function return type check failed, function_name={}, "
+                    "expect_return_type={}, real_return_type is nullptr, 
input_arguments={}",
+                    get_name(), return_type->get_name(), 
get_types_string(arguments));
+        }
+
         // check return types equal.
         if (!(return_type->equals(*func_return_type) ||
               // For null constant argument, `get_return_type` would return
diff --git a/be/test/vec/function/simple_function_factory_test.cpp 
b/be/test/vec/function/simple_function_factory_test.cpp
new file mode 100644
index 00000000000..41ff70c6dac
--- /dev/null
+++ b/be/test/vec/function/simple_function_factory_test.cpp
@@ -0,0 +1,98 @@
+// 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.
+
+#include "vec/functions/simple_function_factory.h"
+
+#include <gtest/gtest.h>
+
+#include <memory>
+
+#include "vec/data_types/data_type_number.h"
+
+namespace doris::vectorized {
+
+class FunctionBeTestMock : public IFunction {
+public:
+    static constexpr auto name = "be_test_mock";
+
+    static FunctionPtr create() { return 
std::make_shared<FunctionBeTestMock>(); }
+
+    String get_name() const override { return name; }
+
+    size_t get_number_of_arguments() const override { return 0; }
+
+    DataTypePtr get_return_type_impl(const DataTypes& arguments) const 
override { return nullptr; }
+
+    Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                        size_t result, size_t input_rows_count) const override 
{
+        return Status::OK();
+    }
+};
+
+class SimpleFunctionFactoryTest : public testing::Test {
+    void SetUp() override {
+        static std::once_flag oc;
+        std::call_once(oc, []() {
+            
SimpleFunctionFactory::instance().register_function<FunctionBeTestMock>();
+        });
+    }
+
+    ColumnsWithTypeAndName arguments(size_t size) {
+        ColumnsWithTypeAndName args;
+        for (size_t i = 0; i < size; ++i) {
+            args.emplace_back(nullptr, std::make_shared<DataTypeInt64>(), "");
+        }
+        return args;
+    }
+
+    void TearDown() override {}
+};
+
+TEST_F(SimpleFunctionFactoryTest, test_return_type_check) {
+    EXPECT_THROW(SimpleFunctionFactory::instance().get_function(
+                         "be_test_mock", {}, std::make_shared<DataTypeInt64>(),
+                         {.enable_decimal256 = false}, 
BeExecVersionManager::get_newest_version()),
+                 doris::Exception);
+}
+
+TEST_F(SimpleFunctionFactoryTest, test_return_all) {
+    auto factory = SimpleFunctionFactory::instance();
+
+    for (auto [name, builder] : factory.function_creators) {
+        auto function = builder();
+        auto func_impl = 
std::dynamic_pointer_cast<FunctionBuilderImpl>(function);
+        EXPECT_NE(func_impl, nullptr);
+        if (func_impl->is_variadic()) {
+            continue;
+        }
+        std::cout << func_impl->get_name() << std::endl;
+        ///TODO: Currently, many DCHECK statements exist within 
get_return_type_impl.
+        // In the future, after replacing all these DCHECK statements with 
exceptions, we will be able to enumerate all the functions.
+
+        // try {
+        //     auto return_type = func_impl->get_return_type_impl(
+        //             arguments(func_impl->get_number_of_arguments()));
+        //     EXPECT_NE(return_type, nullptr) << func_impl->get_name();
+        // } catch (const doris::Exception& e) {
+        //     std::cout << "Exception message: " << e.what() << std::endl; // 
使用what()方法
+        //     SUCCEED();
+        // } catch (...) {
+        // }
+    }
+}
+
+} // namespace doris::vectorized
\ No newline at end of file


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

Reply via email to