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 24750b55f6c8c2..73a87fd7cf22eb 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 @@ class FunctionArrayCumSum : public IFunction { } if (return_type) { return std::make_shared(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 9eca677f0336ce..46cda52516a271 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 @@ class FunctionArrayDifference : public IFunction { if (return_type) { return std::make_shared(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 b1a55e6f1a5290..ea729e7be3f828 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 @@ class FunctionArrayElement : public IFunction { return make_nullable( check_and_get_data_type(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 4c073386e4d60e..bb9dd9c04cc520 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 @@ class FunctionArrayEnumerateUniq : public IFunction { 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 ff987d130cda58..edc214e5f36a76 100644 --- a/be/src/vec/functions/function.h +++ b/be/src/vec/functions/function.h @@ -295,6 +295,14 @@ class FunctionBuilderImpl : public IFunctionBuilder { 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 00000000000000..41ff70c6dac29a --- /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 + +#include + +#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(); } + + 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(); + }); + } + + ColumnsWithTypeAndName arguments(size_t size) { + ColumnsWithTypeAndName args; + for (size_t i = 0; i < size; ++i) { + args.emplace_back(nullptr, std::make_shared(), ""); + } + return args; + } + + void TearDown() override {} +}; + +TEST_F(SimpleFunctionFactoryTest, test_return_type_check) { + EXPECT_THROW(SimpleFunctionFactory::instance().get_function( + "be_test_mock", {}, std::make_shared(), + {.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(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