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