diff --git a/base/base/IPv4andIPv6.h b/base/base/IPv4andIPv6.h index 981198a5ef1..03b21148267 100644 --- a/base/base/IPv4andIPv6.h +++ b/base/base/IPv4andIPv6.h @@ -2,9 +2,54 @@ #include #include +#include +#include "base/Decimal.h" namespace DB { + using IPv4 = StrongTypedef; - using IPv6 = StrongTypedef; + + struct IPv6 : StrongTypedef + { + + constexpr IPv6() = default; + constexpr explicit IPv6(const UInt128 & x) : StrongTypedef(x) {} + constexpr explicit IPv6(UInt128 && x) : StrongTypedef(std::move(x)) {} + + IPv6 & operator=(const UInt128 & rhs) { StrongTypedef::operator=(rhs); return *this; } + IPv6 & operator=(UInt128 && rhs) { StrongTypedef::operator=(std::move(rhs)); return *this; } + + bool operator<(const IPv6 & rhs) const + { + return + memcmp16( + reinterpret_cast(toUnderType().items), + reinterpret_cast(rhs.toUnderType().items) + ) < 0; + } + + bool operator>(const IPv6 & rhs) const + { + return + memcmp16( + reinterpret_cast(toUnderType().items), + reinterpret_cast(rhs.toUnderType().items) + ) > 0; + } + + bool operator==(const IPv6 & rhs) const + { + return + memcmp16( + reinterpret_cast(toUnderType().items), + reinterpret_cast(rhs.toUnderType().items) + ) == 0; + } + + bool operator<=(const IPv6 & rhs) const { return !operator>(rhs); } + bool operator>=(const IPv6 & rhs) const { return !operator<(rhs); } + bool operator!=(const IPv6 & rhs) const { return !operator==(rhs); } + }; + } diff --git a/src/Core/Field.cpp b/src/Core/Field.cpp index f9cd7b67a54..c1842d7e493 100644 --- a/src/Core/Field.cpp +++ b/src/Core/Field.cpp @@ -60,7 +60,7 @@ inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) case Field::Types::IPv6: { IPv6 value; - readBinary(value, buf); + readBinary(value.toUnderType(), buf); return value; } case Field::Types::Int64: diff --git a/src/Core/Field.h b/src/Core/Field.h index 8398c9665d6..3c787389ef6 100644 --- a/src/Core/Field.h +++ b/src/Core/Field.h @@ -514,8 +514,8 @@ public: case Types::Int128: return get() <= rhs.get(); case Types::Int256: return get() <= rhs.get(); case Types::UUID: return get().toUnderType() <= rhs.get().toUnderType(); - case Types::IPv4: return get().toUnderType() <= rhs.get().toUnderType(); - case Types::IPv6: return get().toUnderType() <= rhs.get().toUnderType(); + case Types::IPv4: return get() <= rhs.get(); + case Types::IPv6: return get() <= rhs.get(); case Types::Float64: return get() <= rhs.get(); case Types::String: return get() <= rhs.get(); case Types::Array: return get() <= rhs.get(); diff --git a/src/DataTypes/Serializations/SerializationIPv4andIPv6.h b/src/DataTypes/Serializations/SerializationIPv4andIPv6.h index e246bce9b9e..415e3c5efb2 100644 --- a/src/DataTypes/Serializations/SerializationIPv4andIPv6.h +++ b/src/DataTypes/Serializations/SerializationIPv4andIPv6.h @@ -83,7 +83,7 @@ public: void deserializeBinary(Field & field, ReadBuffer & istr) const override { IPv x; - readBinary(x, istr); + readBinary(x.toUnderType(), istr); field = NearestFieldType(x); } void serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override @@ -92,8 +92,8 @@ public: } void deserializeBinary(IColumn & column, ReadBuffer & istr) const override { - IPv4 x; - readBinary(x, istr); + IPv x; + readBinary(x.toUnderType(), istr); assert_cast &>(column).getData().push_back(x); } void serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const override diff --git a/src/Functions/FunctionsCodingIP.cpp b/src/Functions/FunctionsCodingIP.cpp index 83ddb9aa1ad..112a905f4b0 100644 --- a/src/Functions/FunctionsCodingIP.cpp +++ b/src/Functions/FunctionsCodingIP.cpp @@ -511,11 +511,17 @@ public: DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { - if (!checkAndGetDataType(arguments[0].get())) - throw Exception("Illegal type " + arguments[0]->getName() + - " of argument of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + const auto * dt_uint32 = checkAndGetDataType(arguments[0].get()); + const auto * dt_ipv4 = checkAndGetDataType(arguments[0].get()); + if (!dt_uint32 && !dt_ipv4) + throw Exception( + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", arguments[0]->getName(), getName() + ); - return std::make_shared(16); + if (dt_uint32) + return std::make_shared(16); + return std::make_shared(); } bool useDefaultImplementationForConstants() const override { return true; } @@ -525,7 +531,22 @@ public: const auto & col_type_name = arguments[0]; const ColumnPtr & column = col_type_name.column; - if (const auto * col_in = typeid_cast(column.get())) + if (const auto * col_in = checkAndGetColumn(*column)) + { + auto col_res = ColumnIPv6::create(); + + auto & vec_res = col_res->getData(); + vec_res.resize(col_in->size()); + + const auto & vec_in = col_in->getData(); + + for (size_t i = 0; i < vec_res.size(); ++i) + mapIPv4ToIPv6(vec_in[i], reinterpret_cast(&vec_res[i].toUnderType())); + + return col_res; + } + + if (const auto * col_in = checkAndGetColumn(*column)) { auto col_res = ColumnFixedString::create(IPV6_BINARY_LENGTH); @@ -539,10 +560,11 @@ public: return col_res; } - else - throw Exception("Illegal column " + arguments[0].column->getName() - + " of argument of function " + getName(), - ErrorCodes::ILLEGAL_COLUMN); + + throw Exception( + ErrorCodes::ILLEGAL_COLUMN, + "Illegal column {} of argument of function {}", arguments[0].column->getName(), getName() + ); } private: diff --git a/src/Functions/FunctionsComparison.h b/src/Functions/FunctionsComparison.h index 4bbf7eca6c9..74c35454e6c 100644 --- a/src/Functions/FunctionsComparison.h +++ b/src/Functions/FunctionsComparison.h @@ -842,72 +842,6 @@ private: return res; } - ColumnPtr executeIPv6(const IColumn * c0, const IColumn * c1) const - { - const ColumnIPv6 * c0_string = checkAndGetColumn(c0); - const ColumnIPv6 * c1_string = checkAndGetColumn(c1); - - const ColumnConst * c0_const = checkAndGetColumnConst(c0); - const ColumnConst * c1_const = checkAndGetColumnConst(c1); - - if (!((c0_string || c0_const) && (c1_string || c1_const))) - return nullptr; - - const ColumnIPv6::Container * c0_const_chars = nullptr; - const ColumnIPv6::Container * c1_const_chars = nullptr; - - if (c0_const) - { - const ColumnIPv6 * c0_const_string = checkAndGetColumn(&c0_const->getDataColumn()); - - if (c0_const_string) - c0_const_chars = &c0_const_string->getData(); - else - throw Exception("Logical error: ColumnConst contains not String nor FixedString column", ErrorCodes::ILLEGAL_COLUMN); - } - - if (c1_const) - { - const ColumnIPv6 * c1_const_string = checkAndGetColumn(&c1_const->getDataColumn()); - - if (c1_const_string) - c1_const_chars = &c1_const_string->getData(); - else - throw Exception("Logical error: ColumnConst contains not String nor FixedString column", ErrorCodes::ILLEGAL_COLUMN); - } - - using IPv6Impl = IPv6ComparisonImpl>; - - if (c0_const && c1_const) - { - auto res = executeIPv6(&c0_const->getDataColumn(), &c1_const->getDataColumn()); - if (!res) - return nullptr; - - return ColumnConst::create(res, c0_const->size()); - } - else - { - auto c_res = ColumnUInt8::create(); - ColumnUInt8::Container & vec_res = c_res->getData(); - vec_res.resize(c0->size()); - - if (c0_string && c1_string) - IPv6Impl::ipv6_vector_ipv6_vector(c0_string->getData(), c1_string->getData(), c_res->getData()); - else if (c0_string && c1_const) - IPv6Impl::ipv6_vector_constant(c0_string->getData(), *c1_const_chars, c_res->getData()); - else if (c0_const && c1_string) - IPv6Impl::constant_ipv6_vector(*c0_const_chars, c1_string->getData(), c_res->getData()); - else - throw Exception("Illegal columns " - + c0->getName() + " and " + c1->getName() - + " of arguments of function " + getName(), - ErrorCodes::ILLEGAL_COLUMN); - - return c_res; - } - } - ColumnPtr executeString(const IColumn * c0, const IColumn * c1) const { const ColumnString * c0_string = checkAndGetColumn(c0); @@ -1397,9 +1331,6 @@ public: const bool left_is_float = which_left.isFloat(); const bool right_is_float = which_right.isFloat(); - const bool left_is_ipv6 = which_left.isIPv6(); - const bool right_is_ipv6 = which_right.isIPv6(); - bool date_and_datetime = (which_left.idx != which_right.idx) && (which_left.isDate() || which_left.isDate32() || which_left.isDateTime() || which_left.isDateTime64()) && (which_right.isDate() || which_right.isDate32() || which_right.isDateTime() || which_right.isDateTime64()); @@ -1431,10 +1362,6 @@ public: { return executeTuple(result_type, col_with_type_and_name_left, col_with_type_and_name_right, input_rows_count); } - else if ((left_is_ipv6 && right_is_ipv6) && (res = executeIPv6(col_left_untyped, col_right_untyped))) - { - return res; - } else if (left_is_string && right_is_string && (res = executeString(col_left_untyped, col_right_untyped))) { return res; diff --git a/src/Functions/FunctionsConversion.h b/src/Functions/FunctionsConversion.h index d6fc2a73447..1432789f3a6 100644 --- a/src/Functions/FunctionsConversion.h +++ b/src/Functions/FunctionsConversion.h @@ -1021,7 +1021,7 @@ inline void parseImpl(DataTypeIPv6::FieldType & x, ReadBuffer & rb { IPv6 tmp; readIPv6Text(tmp, rb); - x = tmp.toUnderType(); + x = tmp; } template @@ -1092,7 +1092,7 @@ inline bool tryParseImpl(DataTypeIPv6::FieldType & x, ReadBuffer & if (!tryReadIPv6Text(tmp, rb)) return false; - x = tmp.toUnderType(); + x = tmp; return true; }