From 6bd2d7b7e54f2a1ddaa78eb2a73a6851925f9316 Mon Sep 17 00:00:00 2001 From: "TONG, Zhigao" Date: Thu, 19 Oct 2023 19:34:59 +0800 Subject: [PATCH] This is an automated cherry-pick of #8210 Signed-off-by: ti-chi-bot --- dbms/src/Functions/FunctionsCoding.h | 82 ++++++++++++---- .../Functions/tests/gtest_inet_aton_ntoa.cpp | 98 ++++++++++++++++--- 2 files changed, 149 insertions(+), 31 deletions(-) diff --git a/dbms/src/Functions/FunctionsCoding.h b/dbms/src/Functions/FunctionsCoding.h index 657ce202655..3810bce594b 100644 --- a/dbms/src/Functions/FunctionsCoding.h +++ b/dbms/src/Functions/FunctionsCoding.h @@ -776,49 +776,91 @@ class FunctionIPv4NumToString : public IFunction DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { +<<<<<<< HEAD if (!checkDataType(&*arguments[0])) throw Exception( fmt::format("Illegal type {} of argument of function {}, expected UInt32", arguments[0]->getName(), getName()), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); return std::make_shared(); +======= + if (arguments[0]->isInteger()) + return makeNullable(std::make_shared()); + throw Exception( + fmt::format( + "Illegal type {} of argument of function {}, expected integer", + arguments[0]->getName(), + getName()), + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); +>>>>>>> ea99379f4f (Fix the compatibility issue in func `FunctionIPv4NumToString` (#8210)) } bool useDefaultImplementationForNulls() const override { return true; } bool useDefaultImplementationForConstants() const override { return true; } - void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) const override + template + static void executeImplColumnInteger(Block & block, const ColumnContainer & vec_in, size_t result) { - const ColumnPtr & column = block.getByPosition(arguments[0]).column; - - if (const auto * col = typeid_cast(column.get())) - { - const ColumnUInt32::Container & vec_in = col->getData(); + auto col_res = ColumnString::create(); + auto nullmap_res = ColumnUInt8::create(); + ColumnString::Chars_t & vec_res = col_res->getChars(); + ColumnString::Offsets & offsets_res = col_res->getOffsets(); + ColumnUInt8::Container & vec_res_nullmap = nullmap_res->getData(); - auto col_res = ColumnString::create(); + vec_res.resize(vec_in.size() * (IPV4_MAX_TEXT_LENGTH + 1)); /// the longest value is: 255.255.255.255\0 + offsets_res.resize(vec_in.size()); + vec_res_nullmap.assign(vec_in.size(), static_cast(0)); - ColumnString::Chars_t & vec_res = col_res->getChars(); - ColumnString::Offsets & offsets_res = col_res->getOffsets(); + char * begin = reinterpret_cast(&vec_res[0]); + char * pos = begin; - vec_res.resize(vec_in.size() * (IPV4_MAX_TEXT_LENGTH + 1)); /// the longest value is: 255.255.255.255\0 - offsets_res.resize(vec_in.size()); - char * begin = reinterpret_cast(&vec_res[0]); - char * pos = begin; - - for (size_t i = 0; i < vec_in.size(); ++i) + for (size_t i = 0; i < vec_in.size(); ++i) + { + auto && value = vec_in[i]; + if (/*always `false` for unsigned integer*/ value < 0 + || /*auto optimized by compiler*/ static_cast(value) > std::numeric_limits::max()) { - formatIP(vec_in[i], pos); - offsets_res[i] = pos - begin; + *pos++ = 0; + vec_res_nullmap[i] = 1; } + else + { + formatIP(static_cast(value), pos); + } + offsets_res[i] = pos - begin; + } - vec_res.resize(pos - begin); + vec_res.resize(pos - begin); + block.getByPosition(result).column = ColumnNullable::create(std::move(col_res), std::move(nullmap_res)); + } - block.getByPosition(result).column = std::move(col_res); - } + void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) const override + { + const ColumnPtr & column = block.getByPosition(arguments[0]).column; + +#define DISPATCH(ColType) \ + else if (const auto * col = typeid_cast(column.get())) \ + { \ + const typename ColType::Container & vec_in = col->getData(); \ + executeImplColumnInteger(block, vec_in, result); \ + } + + if (false) {} // NOLINT + DISPATCH(ColumnUInt64) + DISPATCH(ColumnInt64) + DISPATCH(ColumnUInt32) + DISPATCH(ColumnInt32) + DISPATCH(ColumnUInt16) + DISPATCH(ColumnInt16) + DISPATCH(ColumnUInt8) + DISPATCH(ColumnInt8) else + { throw Exception( fmt::format("Illegal column {} of argument of function {}", block.getByPosition(arguments[0]).column->getName(), getName()), ErrorCodes::ILLEGAL_COLUMN); + } +#undef DISPATCH } }; diff --git a/dbms/src/Functions/tests/gtest_inet_aton_ntoa.cpp b/dbms/src/Functions/tests/gtest_inet_aton_ntoa.cpp index 57e0da3ea65..5dc5aacf358 100644 --- a/dbms/src/Functions/tests/gtest_inet_aton_ntoa.cpp +++ b/dbms/src/Functions/tests/gtest_inet_aton_ntoa.cpp @@ -23,8 +23,6 @@ #include #include -#include -#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsign-compare" @@ -120,34 +118,112 @@ try } CATCH -TEST_F(TestInetAtonNtoa, InetNtoa) -try + +template +static void TestInetAtonNtoaImpl(TestInetAtonNtoa & test) { const String func_name = "IPv4NumToString"; // empty column ASSERT_COLUMN_EQ( createColumn>({}), - executeFunction(func_name, createColumn>({}))); + test.executeFunction(func_name, createColumn>({}))); +<<<<<<< HEAD ASSERT_COLUMN_EQ( createColumn({}), executeFunction(func_name, createColumn({}))); +======= + ASSERT_COLUMN_EQ(createColumn>({}), test.executeFunction(func_name, createColumn({}))); +>>>>>>> ea99379f4f (Fix the compatibility issue in func `FunctionIPv4NumToString` (#8210)) // const null-only column ASSERT_COLUMN_EQ( createConstColumn>(1, {}), - executeFunction(func_name, createConstColumn>(1, {}))); + test.executeFunction(func_name, createConstColumn>(1, {}))); - // const non-null column - ASSERT_COLUMN_EQ( - createConstColumn(1, "0.0.0.1"), - executeFunction(func_name, createConstColumn>(1, 1))); + if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({"0.0.0.255"}), + test.executeFunction(func_name, createColumn>({std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({{}, "0.0.0.127"}), + test.executeFunction(func_name, createColumn>({-1, std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({"0.0.255.255"}), + test.executeFunction(func_name, createColumn>({std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({{}, "0.0.127.255"}), + test.executeFunction(func_name, createColumn>({-1, std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({"255.255.255.255"}), + test.executeFunction(func_name, createColumn>({std::numeric_limits::max()}))); + ASSERT_COLUMN_EQ( + createColumn>( + {"1.2.3.4", "0.1.0.1", "0.255.0.255", "0.1.2.3", "0.0.0.0", "1.0.1.0", "111.0.21.12"}), + test.executeFunction( + func_name, + createColumn>({16909060, 65537, 16711935, 66051, 0, 16777472, 1862276364}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({{}, "127.255.255.255"}), + test.executeFunction(func_name, createColumn>({-1, std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({"255.255.255.255", {}}), + test.executeFunction( + func_name, + createColumn>({std::numeric_limits::max(), std::numeric_limits::max()}))); + } + else if constexpr (std::is_same_v) + { + ASSERT_COLUMN_EQ( + createColumn>({"255.255.255.255", {}, {}}), + test.executeFunction( + func_name, + createColumn>( + {std::numeric_limits::max(), -1, std::numeric_limits::max()}))); + } +} +<<<<<<< HEAD // normal cases ASSERT_COLUMN_EQ( createColumn>({"1.2.3.4", "0.1.0.1", "0.255.0.255", "0.1.2.3", "0.0.0.0", "1.0.1.0", "111.0.21.12"}), executeFunction(func_name, createColumn>({16909060, 65537, 16711935, 66051, 0, 16777472, 1862276364}))); +======= + +TEST_F(TestInetAtonNtoa, InetNtoa) +try +{ +#define M(T) TestInetAtonNtoaImpl(*this); + M(UInt8); + M(Int8); + M(UInt16); + M(Int16); + M(UInt32); + M(Int32); + M(UInt64); + M(Int64); +#undef M +>>>>>>> ea99379f4f (Fix the compatibility issue in func `FunctionIPv4NumToString` (#8210)) } CATCH @@ -162,7 +238,7 @@ try std::uniform_int_distribution dist; InferredDataVector> num_vec; - for (size_t i = 0; i < 10000; ++i) + for (size_t i = 0; i < 512; ++i) { num_vec.emplace_back(dist(mt)); }