diff --git a/be/src/vec/common/unaligned.h b/be/src/vec/common/unaligned.h index d56eca59b2..ee807c606e 100644 --- a/be/src/vec/common/unaligned.h +++ b/be/src/vec/common/unaligned.h @@ -20,8 +20,9 @@ #pragma once -#include - +#include +#include +#include #include template @@ -40,3 +41,31 @@ void unaligned_store(void* address, const typename std::enable_if::type static_assert(std::is_trivially_copyable_v); memcpy(address, &src, sizeof(src)); } + +inline void reverse_memcpy(void* dst, const void* src, size_t size) { + uint8_t* uint_dst = reinterpret_cast(dst) + size; // Perform addition here + const uint8_t* uint_src = reinterpret_cast(src); + + while (size) { + --uint_dst; + *uint_dst = *uint_src; + ++uint_src; + --size; + } +} + +template +inline T unaligned_load_endian(const void* address) { + T res {}; + if constexpr (std::endian::native == endian) { + memcpy(&res, address, sizeof(res)); + } else { + reverse_memcpy(&res, address, sizeof(res)); + } + return res; +} + +template +inline T unaligned_load_little_endian(const void* address) { + return unaligned_load_endian(address); +} \ No newline at end of file diff --git a/be/src/vec/functions/function_ip.cpp b/be/src/vec/functions/function_ip.cpp index 3faa6a42d8..140100d22b 100644 --- a/be/src/vec/functions/function_ip.cpp +++ b/be/src/vec/functions/function_ip.cpp @@ -27,6 +27,7 @@ void register_function_ip(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_alias(FunctionIPv4StringToNum::name, "inet_aton"); + factory.register_function(); factory.register_alias(FunctionIPv6NumToString::name, "inet6_ntoa"); factory.register_function>(); @@ -34,6 +35,9 @@ void register_function_ip(SimpleFunctionFactory& factory) { factory.register_function>(); factory.register_alias(FunctionIPv6StringToNum::name, "inet6_aton"); + + factory.register_function(); + factory.register_function(); factory.register_function>(); factory.register_function>(); factory.register_function(); diff --git a/be/src/vec/functions/function_ip.h b/be/src/vec/functions/function_ip.h index 313ad0fdd6..8a260b8fd8 100644 --- a/be/src/vec/functions/function_ip.h +++ b/be/src/vec/functions/function_ip.h @@ -364,44 +364,6 @@ ColumnPtr convertToIPv6(const StringColumnType& string_column, vec_null_map_to = &col_null_map_to->get_data(); } - /// This is a special treatment for source column of type String - /// to preserve previous behavior when IPv6 was a domain type of String - if constexpr (std::is_same_v) { - if (string_column.get_offsets()[0] - 1 == IPV6_BINARY_LENGTH) { - if constexpr (std::is_same_v) { - auto col_res = ColumnString::create(); - - if constexpr (exception_mode == IPStringToNumExceptionMode::Null) { - col_null_map_to = ColumnUInt8::create(column_size, false); - if (null_map) { - memcpy(col_null_map_to->get_data().data(), null_map->data(), column_size); - } - - return ColumnNullable::create(std::move(col_res), std::move(col_null_map_to)); - } - - return col_res; - } else { - auto col_res = ColumnIPv6::create(); - auto& vec_res = col_res->get_data(); - - vec_res.resize(column_size); - memcpy(vec_res.data(), string_column.get_chars().data(), - column_size * IPV6_BINARY_LENGTH); - - if constexpr (exception_mode == IPStringToNumExceptionMode::Null) { - col_null_map_to = ColumnUInt8::create(column_size, false); - if (null_map) { - memcpy(col_null_map_to->get_data().data(), null_map->data(), column_size); - } - return ColumnNullable::create(std::move(col_res), std::move(col_null_map_to)); - } - - return col_res; - } - } - } - auto column_create = [](size_t column_size) -> typename ToColumn::MutablePtr { if constexpr (std::is_same_v) { auto column_string = ColumnString::create(); @@ -833,4 +795,94 @@ private: } }; -} // namespace doris::vectorized \ No newline at end of file +class FunctionIsIPv4Compat : public IFunction { +public: + static constexpr auto name = "is_ipv4_compat"; + static FunctionPtr create() { return std::make_shared(); } + + String get_name() const override { return name; } + + size_t get_number_of_arguments() const override { return 1; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + return std::make_shared(); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) const override { + const ColumnPtr& column = block.get_by_position(arguments[0]).column; + const auto* col_in = check_and_get_column(column.get()); + + if (!col_in) + throw Exception(ErrorCode::INVALID_ARGUMENT, + "Illegal column {} of argument of function {}, expected String", + column->get_name(), get_name()); + size_t col_size = col_in->size(); + auto col_res = ColumnUInt8::create(col_size, 0); + auto& col_res_data = col_res->get_data(); + + for (size_t i = 0; i < col_size; ++i) { + auto ipv4_in = col_in->get_data_at(i); + if (is_ipv4_compat(reinterpret_cast(ipv4_in.data))) { + col_res_data[i] = 1; + } + } + + block.replace_by_position(result, std::move(col_res)); + return Status::OK(); + } + +private: + static bool is_ipv4_compat(const UInt8* address) { + return (unaligned_load_little_endian(address) == 0) && + (unaligned_load_little_endian(address + 8) == 0) && + (unaligned_load_little_endian(address + 12) != 0); + } +}; + +class FunctionIsIPv4Mapped : public IFunction { +public: + static constexpr auto name = "is_ipv4_mapped"; + static FunctionPtr create() { return std::make_shared(); } + + String get_name() const override { return name; } + + size_t get_number_of_arguments() const override { return 1; } + + DataTypePtr get_return_type_impl(const DataTypes& arguments) const override { + return std::make_shared(); + } + + Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments, + size_t result, size_t input_rows_count) const override { + const ColumnPtr& column = block.get_by_position(arguments[0]).column; + const auto* col_in = check_and_get_column(column.get()); + + if (!col_in) + throw Exception(ErrorCode::INVALID_ARGUMENT, + "Illegal column {} of argument of function {}, expected String", + column->get_name(), get_name()); + size_t col_size = col_in->size(); + auto col_res = ColumnUInt8::create(col_size, 0); + auto& col_res_data = col_res->get_data(); + + for (size_t i = 0; i < col_size; ++i) { + auto ipv4_in = col_in->get_data_at(i); + if (is_ipv4_mapped(reinterpret_cast(ipv4_in.data))) { + col_res_data[i] = 1; + } + } + + block.replace_by_position(result, std::move(col_res)); + return Status::OK(); + } + +private: + static bool is_ipv4_mapped(const UInt8* address) { + return (unaligned_load_little_endian(address) == 0) && + ((unaligned_load_little_endian(address + 8) & 0x00000000FFFFFFFFULL) == + 0x00000000FFFF0000ULL); + } +}; + +} // namespace doris::vectorized diff --git a/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md b/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md new file mode 100644 index 0000000000..84c5aff9b6 --- /dev/null +++ b/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md @@ -0,0 +1,65 @@ +--- +{ +"title": "IS_IPV4_COMPAT", +"language": "en" +} +--- + + + +## IS_IPV4_COMPAT + + + +IS_IPV4_COMPAT + + + +### description + +#### Syntax + +`VARCHAR IS_IPV4_COMPAT(INET6_ATON(VARCHAR ipv4_addr))` + +This function takes an IPv6 address represented in numeric form as a binary string, as returned by INET6_ATON(). +It returns 1 if the argument is a valid IPv4-compatible IPv6 address, 0 otherwise (unless expr is NULL, in which case the function returns NULL). +IPv4-compatible addresses have the form ::ipv4_address. + +### example + +``` +mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::ffff:10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 0 | ++-----------+ +1 row in set (0.02 sec) + +mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 1 | ++-----------+ +1 row in set (0.03 sec) +``` + +### keywords + +IS_IPV4_COMPAT, IP \ No newline at end of file diff --git a/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md b/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md new file mode 100644 index 0000000000..9e338eb135 --- /dev/null +++ b/docs/en/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md @@ -0,0 +1,69 @@ +--- +{ +"title": "IS_IPV4_MAPPED", +"language": "en" +} +--- + + + +## IS_IPV4_MAPPED + + + +IS_IPV4_MAPPED + + + +### description + +#### Syntax + +`VARCHAR IS_IPV4_MAPPED(INET6_ATON(VARCHAR ipv4_addr))` + +This function takes an IPv6 address represented in numeric form as a binary string, as returned by INET6_ATON(). +It returns 1 if the argument is a valid IPv4-mapped IPv6 address, 0 otherwise, unless expr is NULL, in which case the function returns NULL. +IPv4-mapped addresses have the form ::ffff:ipv4_address. + +### notice + +`When the source input doesn't have a prefix of '::ffff:', but if it's still a valid ipv4 address, this result will also be 1 for the reason that the INET6_ATON() automatically adds the prefix for it.` + +### example + +``` +mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 1 | ++-----------+ +1 row in set (0.02 sec) + +mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 0 | ++-----------+ +1 row in set (0.03 sec) +``` + +### keywords + +IS_IPV4_MAPPED, IP \ No newline at end of file diff --git a/docs/sidebars.json b/docs/sidebars.json index 6b94989d18..bda6b8da31 100644 --- a/docs/sidebars.json +++ b/docs/sidebars.json @@ -811,11 +811,12 @@ "sql-manual/sql-functions/ip-functions/ipv4-string-to-num-or-null", "sql-manual/sql-functions/ip-functions/ipv6-num-to-string", "sql-manual/sql-functions/ip-functions/inet6-ntoa", - "sql-manual/sql-functions/ip-functions/ipv6-num-to-string", + "sql-manual/sql-functions/ip-functions/ipv6-string-to-num", "sql-manual/sql-functions/ip-functions/inet6-aton", "sql-manual/sql-functions/ip-functions/ipv6-string-to-num-or-default", - "sql-manual/sql-functions/ip-functions/ipv6-string-to-num-or-null" - + "sql-manual/sql-functions/ip-functions/ipv6-string-to-num-or-null", + "sql-manual/sql-functions/ip-functions/is-ipv4-compat", + "sql-manual/sql-functions/ip-functions/is-ipv4-mapped" ] }, { diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md new file mode 100644 index 0000000000..fba93b8343 --- /dev/null +++ b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-compat.md @@ -0,0 +1,65 @@ +--- +{ +"title": "IS_IPV4_COMPAT", +"language": "zh-CN" +} +--- + + + +## IS_IPV4_COMPAT + + + +IS_IPV4_COMPAT + + + +### description + +#### Syntax + +`VARCHAR IS_IPV4_COMPAT(INET6_ATON(VARCHAR ipv4_addr))` + +该函数采用以数字形式表示的二进制字符串形式的 IPv6 地址,由 INET6_ATON() 返回。 +如果参数是有效的 IPv4 兼容 IPv6 地址,则返回 1,否则返回 0(除非 expr 为 NULL,在这种情况下该函数返回 NULL)。 +IPv4 兼容地址的格式为::ipv4_address。 + +### example + +``` +mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::ffff:10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 0 | ++-----------+ +1 row in set (0.02 sec) + +mysql> SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 1 | ++-----------+ +1 row in set (0.03 sec) +``` + +### keywords + +IS_IPV4_COMPAT, IP \ No newline at end of file diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md new file mode 100644 index 0000000000..66de402220 --- /dev/null +++ b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/is-ipv4-mapped.md @@ -0,0 +1,68 @@ +--- +{ +"title": "IS_IPV4_MAPPED", +"language": "zh-CN" +} +--- + + + +## IS_IPV4_MAPPED + + + +IS_IPV4_MAPPED + + + +### description + +#### Syntax + +`VARCHAR IS_IPV4_MAPPED(INET6_ATON(VARCHAR ipv4_addr))` + +该函数采用以数字形式表示的二进制字符串形式的lPv6地址,由INET6_ATON返回。 +如果参数是有效的IPv4映射IPv6地址,则返回1,否则返回0,除非expr为 NULL,在这种情况下该函数返回NULL。 +IPv4映射地址的格式为::ffff:ipv4_address + +### notice +`当源输入没有'::ffff:'前缀时,但如果它仍然是有效的ipv4地址,则该结果也将为1,因为INET6_ATON()会自动为有效的ipv4地址添加前缀。` + +### example + +``` +mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 1 | ++-----------+ +1 row in set (0.02 sec) + +mysql> SELECT IS_IPV4_MAPPED(INET6_ATON('::10.0.5.9')) AS is_result; ++-----------+ +| is_result | ++-----------+ +| 0 | ++-----------+ +1 row in set (0.03 sec) +``` + +### keywords + +IS_IPV4_MAPPED, IP \ No newline at end of file diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index f4f7af5cf3..68da4df08a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -203,6 +203,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToN import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrDefault; import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrNull; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpAddressInRange; +import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4Compat; +import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4Mapped; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4String; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv6String; import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonArray; @@ -609,6 +611,8 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(Ipv6StringToNum.class, "ipv6_string_to_num", "inet6_aton"), scalar(Ipv6StringToNumOrDefault.class, "ipv6_string_to_num_or_default"), scalar(Ipv6StringToNumOrNull.class, "ipv6_string_to_num_or_null"), + scalar(IsIpv4Compat.class, "is_ipv4_compat"), + scalar(IsIpv4Mapped.class, "is_ipv4_mapped"), scalar(IsIpv4String.class, "is_ipv4_string"), scalar(IsIpv6String.class, "is_ipv6_string"), scalar(IsIpAddressInRange.class, "is_ip_address_in_range"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Compat.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Compat.java new file mode 100644 index 0000000000..684eee0e9c --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Compat.java @@ -0,0 +1,67 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.BooleanType; +import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * scalar function is_ipv4_compat + */ +public class IsIpv4Compat extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BooleanType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(BooleanType.INSTANCE).args(StringType.INSTANCE)); + + public IsIpv4Compat(Expression arg0) { + super("is_ipv4_compat", arg0); + } + + @Override + public IsIpv4Compat withChildren(List children) { + Preconditions.checkArgument(children.size() == 1, + "is_ipv4_compat accept 1 args, but got %s (%s)", + children.size(), + children); + return new IsIpv4Compat(children.get(0)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitIsIpv4Compat(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Mapped.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Mapped.java new file mode 100644 index 0000000000..c3640af543 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/IsIpv4Mapped.java @@ -0,0 +1,67 @@ +// 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. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.BooleanType; +import org.apache.doris.nereids.types.StringType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * scalar function is_ipv4_mapped + */ +public class IsIpv4Mapped extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(BooleanType.INSTANCE).args(VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(BooleanType.INSTANCE).args(StringType.INSTANCE)); + + public IsIpv4Mapped(Expression arg0) { + super("is_ipv4_mapped", arg0); + } + + @Override + public IsIpv4Mapped withChildren(List children) { + Preconditions.checkArgument(children.size() == 1, + "is_ipv4_mapped accept 1 args, but got %s (%s)", + children.size(), + children); + return new IsIpv4Mapped(children.get(0)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitIsIpv4Mapped(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java index 899a31abbd..01823f7819 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java @@ -199,6 +199,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToN import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrDefault; import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrNull; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpAddressInRange; +import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4Compat; +import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4Mapped; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv4String; import org.apache.doris.nereids.trees.expressions.functions.scalar.IsIpv6String; import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonArray; @@ -1155,6 +1157,14 @@ public interface ScalarFunctionVisitor { return visitScalarFunction(ipv6StringToNumOrNull, context); } + default R visitIsIpv4Compat(IsIpv4Compat isIpv4Compat, C context) { + return visitScalarFunction(isIpv4Compat, context); + } + + default R visitIsIpv4Mapped(IsIpv4Mapped isIpv4Mapped, C context) { + return visitScalarFunction(isIpv4Mapped, context); + } + default R visitIsIpv4String(IsIpv4String isIpv4String, C context) { return visitScalarFunction(isIpv4String, context); } diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 973a467562..6a6ff96e83 100644 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -2014,6 +2014,10 @@ visible_functions = { [['ipv6_string_to_num_or_default'], 'STRING', ['STRING'], 'ALWAYS_NOT_NULLABLE'], [['ipv6_string_to_num_or_null'], 'VARCHAR', ['VARCHAR'], 'ALWAYS_NULLABLE'], [['ipv6_string_to_num_or_null'], 'STRING', ['STRING'], 'ALWAYS_NULLABLE'], + [['is_ipv4_compat'], 'BOOLEAN', ['VARCHAR'], ''], + [['is_ipv4_compat'], 'BOOLEAN', ['STRING'], ''], + [['is_ipv4_mapped'], 'BOOLEAN', ['VARCHAR'], ''], + [['is_ipv4_mapped'], 'BOOLEAN', ['STRING'], ''], [['is_ipv4_string'], 'BOOLEAN', ['VARCHAR'], ''], [['is_ipv4_string'], 'BOOLEAN', ['STRING'], ''], [['is_ipv6_string'], 'BOOLEAN', ['VARCHAR'], ''], diff --git a/regression-test/data/nereids_function_p0/ip_functions.out b/regression-test/data/nereids_function_p0/ip_functions.out index 2e3b749a15..914b5ccd68 100644 --- a/regression-test/data/nereids_function_p0/ip_functions.out +++ b/regression-test/data/nereids_function_p0/ip_functions.out @@ -162,4 +162,34 @@ false true -- !ip55 -- -false \ No newline at end of file +false + +-- !ip56 -- +true + +-- !ip57 -- +false + +-- !ip58 -- +false + +-- !ip59 -- +true + +-- !ip60 -- +false + +-- !ip61 -- +true + +-- !ip62 -- +false + +-- !ip63 -- +true + +-- !ip64 -- +false + +-- !ip65 -- +true \ No newline at end of file diff --git a/regression-test/data/query_p0/sql_functions/ip_functions/test_ip_functions.out b/regression-test/data/query_p0/sql_functions/ip_functions/test_ip_functions.out index 71f02449d3..1837acc4ba 100644 --- a/regression-test/data/query_p0/sql_functions/ip_functions/test_ip_functions.out +++ b/regression-test/data/query_p0/sql_functions/ip_functions/test_ip_functions.out @@ -137,4 +137,34 @@ AAAAAAAAFFFFFFFFFFFFFFFFAAAAAAAA 00000000000000000000FFFFC0A80001 -- !sql -- -2A0206B8000000000000000000000011 \ No newline at end of file +2A0206B8000000000000000000000011 + +-- !sql -- +true + +-- !sql -- +false + +-- !sql -- +false + +-- !sql -- +true + +-- !sql -- +false + +-- !sql -- +true + +-- !sql -- +false + +-- !sql -- +true + +-- !sql -- +false + +-- !sql -- +true \ No newline at end of file diff --git a/regression-test/suites/nereids_function_p0/ip_functions.groovy b/regression-test/suites/nereids_function_p0/ip_functions.groovy index 1ac0010209..b5d4d177e8 100644 --- a/regression-test/suites/nereids_function_p0/ip_functions.groovy +++ b/regression-test/suites/nereids_function_p0/ip_functions.groovy @@ -77,4 +77,16 @@ suite("ip_functions") { qt_ip53 "SELECT is_ipv4_string('255.255.255.256');" qt_ip54 "SELECT is_ipv6_string('2001:5b0:23ff:fffa::113');" qt_ip55 "SELECT is_ipv6_string('2001:da8:e000:1691:2eaa:7eff:ffe7:7924e');" + + qt_ip56 "SELECT is_ipv4_compat(inet6_aton('::10.0.5.9'));" + qt_ip57 "SELECT is_ipv4_compat(inet6_aton('::ffff:10.0.5.9'));" + qt_ip58 "SELECT is_ipv4_compat(inet6_aton('::'));" + qt_ip59 "SELECT is_ipv4_compat(inet6_aton('::c0a8:0001'));" + qt_ip60 "SELECT is_ipv4_compat(inet6_aton('::0.0.0.0'));" + qt_ip61 "SELECT is_ipv4_compat(inet6_aton('::255.255.255.255'));" + + qt_ip62 "SELECT is_ipv4_mapped(inet6_aton('::10.0.5.9'));" + qt_ip63 "SELECT is_ipv4_mapped(inet6_aton('::ffff:10.0.5.9'));" + qt_ip64 "SELECT is_ipv4_mapped(inet6_aton('::'));" + qt_ip65 "SELECT is_ipv4_mapped(inet6_aton('::ffff:c0a8:0001'));" } \ No newline at end of file diff --git a/regression-test/suites/query_p0/sql_functions/ip_functions/test_ip_functions.groovy b/regression-test/suites/query_p0/sql_functions/ip_functions/test_ip_functions.groovy index 828de6cbe4..c5ff6d36a1 100644 --- a/regression-test/suites/query_p0/sql_functions/ip_functions/test_ip_functions.groovy +++ b/regression-test/suites/query_p0/sql_functions/ip_functions/test_ip_functions.groovy @@ -67,4 +67,16 @@ suite("test_ip_functions", "arrow_flight_sql") { qt_sql "SELECT hex(ipv6_string_to_num_or_null('aaaa:aaaa:ffff:ffff:ffff:ffff:aaaa:aaaa'));" qt_sql "SELECT hex(inet6_aton('192.168.0.1'));" qt_sql "SELECT hex(inet6_aton('2a02:6b8::11'));" + + qt_sql "SELECT is_ipv4_compat(inet6_aton('::10.0.5.9'));" + qt_sql "SELECT is_ipv4_compat(inet6_aton('::ffff:10.0.5.9'));" + qt_sql "SELECT is_ipv4_compat(inet6_aton('::'));" + qt_sql "SELECT is_ipv4_compat(inet6_aton('::c0a8:0001'));" + qt_sql "SELECT is_ipv4_compat(inet6_aton('::0.0.0.0'));" + qt_sql "SELECT is_ipv4_compat(inet6_aton('::255.255.255.255'));" + + qt_sql "SELECT is_ipv4_mapped(inet6_aton('::10.0.5.9'));" + qt_sql "SELECT is_ipv4_mapped(inet6_aton('::ffff:10.0.5.9'));" + qt_sql "SELECT is_ipv4_mapped(inet6_aton('::'));" + qt_sql "SELECT is_ipv4_mapped(inet6_aton('::ffff:c0a8:0001'));" }