This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new d6ed4149f5b [feature](function) support ip function is_ipv4_compat,
is_ipv4_mapped (#29954)
d6ed4149f5b is described below
commit d6ed4149f5b2b15e97a5a8861387141749c0339e
Author: Chester <[email protected]>
AuthorDate: Sun Jan 21 10:51:58 2024 +0800
[feature](function) support ip function is_ipv4_compat, is_ipv4_mapped
(#29954)
---
be/src/vec/common/unaligned.h | 33 +++++-
be/src/vec/functions/function_ip.cpp | 4 +
be/src/vec/functions/function_ip.h | 130 ++++++++++++++-------
.../sql-functions/ip-functions/is-ipv4-compat.md | 65 +++++++++++
.../sql-functions/ip-functions/is-ipv4-mapped.md | 69 +++++++++++
docs/sidebars.json | 7 +-
.../sql-functions/ip-functions/is-ipv4-compat.md | 65 +++++++++++
.../sql-functions/ip-functions/is-ipv4-mapped.md | 68 +++++++++++
.../doris/catalog/BuiltinScalarFunctions.java | 4 +
.../expressions/functions/scalar/IsIpv4Compat.java | 67 +++++++++++
.../expressions/functions/scalar/IsIpv4Mapped.java | 67 +++++++++++
.../expressions/visitor/ScalarFunctionVisitor.java | 10 ++
gensrc/script/doris_builtins_functions.py | 4 +
.../data/nereids_function_p0/ip_functions.out | 32 ++++-
.../ip_functions/test_ip_functions.out | 32 ++++-
.../suites/nereids_function_p0/ip_functions.groovy | 12 ++
.../ip_functions/test_ip_functions.groovy | 12 ++
17 files changed, 635 insertions(+), 46 deletions(-)
diff --git a/be/src/vec/common/unaligned.h b/be/src/vec/common/unaligned.h
index d56eca59b23..ee807c606e5 100644
--- a/be/src/vec/common/unaligned.h
+++ b/be/src/vec/common/unaligned.h
@@ -20,8 +20,9 @@
#pragma once
-#include <string.h>
-
+#include <bit>
+#include <cstdint>
+#include <cstring>
#include <type_traits>
template <typename T>
@@ -40,3 +41,31 @@ void unaligned_store(void* address, const typename
std::enable_if<true, T>::type
static_assert(std::is_trivially_copyable_v<T>);
memcpy(address, &src, sizeof(src));
}
+
+inline void reverse_memcpy(void* dst, const void* src, size_t size) {
+ uint8_t* uint_dst = reinterpret_cast<uint8_t*>(dst) + size; // Perform
addition here
+ const uint8_t* uint_src = reinterpret_cast<const uint8_t*>(src);
+
+ while (size) {
+ --uint_dst;
+ *uint_dst = *uint_src;
+ ++uint_src;
+ --size;
+ }
+}
+
+template <std::endian endian, typename T>
+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 <typename T>
+inline T unaligned_load_little_endian(const void* address) {
+ return unaligned_load_endian<std::endian::little, T>(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 3faa6a42d8c..140100d22b3 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<FunctionIPv4StringToNum<IPStringToNumExceptionMode::Null>>();
factory.register_alias(FunctionIPv4StringToNum<IPStringToNumExceptionMode::Throw>::name,
"inet_aton");
+
factory.register_function<FunctionIPv6NumToString>();
factory.register_alias(FunctionIPv6NumToString::name, "inet6_ntoa");
factory.register_function<FunctionIPv6StringToNum<IPStringToNumExceptionMode::Throw>>();
@@ -34,6 +35,9 @@ void register_function_ip(SimpleFunctionFactory& factory) {
factory.register_function<FunctionIPv6StringToNum<IPStringToNumExceptionMode::Null>>();
factory.register_alias(FunctionIPv6StringToNum<IPStringToNumExceptionMode::Throw>::name,
"inet6_aton");
+
+ factory.register_function<FunctionIsIPv4Compat>();
+ factory.register_function<FunctionIsIPv4Mapped>();
factory.register_function<FunctionIsIPString<IPv4>>();
factory.register_function<FunctionIsIPString<IPv6>>();
factory.register_function<FunctionIsIPAddressInRange>();
diff --git a/be/src/vec/functions/function_ip.h
b/be/src/vec/functions/function_ip.h
index 313ad0fdd65..8a260b8fd82 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<StringColumnType, ColumnString>) {
- if (string_column.get_offsets()[0] - 1 == IPV6_BINARY_LENGTH) {
- if constexpr (std::is_same_v<ToColumn, ColumnString>) {
- 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<ToColumn, ColumnString>) {
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<FunctionIsIPv4Compat>(); }
+
+ 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<DataTypeUInt8>();
+ }
+
+ 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<ColumnString>(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<const UInt8*>(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<UInt64>(address) == 0) &&
+ (unaligned_load_little_endian<UInt32>(address + 8) == 0) &&
+ (unaligned_load_little_endian<UInt32>(address + 12) != 0);
+ }
+};
+
+class FunctionIsIPv4Mapped : public IFunction {
+public:
+ static constexpr auto name = "is_ipv4_mapped";
+ static FunctionPtr create() { return
std::make_shared<FunctionIsIPv4Mapped>(); }
+
+ 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<DataTypeUInt8>();
+ }
+
+ 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<ColumnString>(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<const UInt8*>(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<UInt64>(address) == 0) &&
+ ((unaligned_load_little_endian<UInt64>(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 00000000000..84c5aff9b63
--- /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"
+}
+---
+
+<!--
+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.
+-->
+
+## IS_IPV4_COMPAT
+
+<version since="dev">
+
+IS_IPV4_COMPAT
+
+</version>
+
+### 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 00000000000..9e338eb1353
--- /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"
+}
+---
+
+<!--
+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.
+-->
+
+## IS_IPV4_MAPPED
+
+<version since="dev">
+
+IS_IPV4_MAPPED
+
+</version>
+
+### 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 6b94989d180..bda6b8da310 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 00000000000..fba93b83430
--- /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"
+}
+---
+
+<!--
+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.
+-->
+
+## IS_IPV4_COMPAT
+
+<version since="dev">
+
+IS_IPV4_COMPAT
+
+</version>
+
+### 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 00000000000..66de4022209
--- /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"
+}
+---
+
+<!--
+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.
+-->
+
+## IS_IPV4_MAPPED
+
+<version since="dev">
+
+IS_IPV4_MAPPED
+
+</version>
+
+### 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 f4f7af5cf38..68da4df08ab 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 00000000000..684eee0e9c9
--- /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<FunctionSignature> 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<Expression> 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<FunctionSignature> getSignatures() {
+ return SIGNATURES;
+ }
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> 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 00000000000..c3640af5437
--- /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<FunctionSignature> 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<Expression> 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<FunctionSignature> getSignatures() {
+ return SIGNATURES;
+ }
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> 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 899a31abbd7..01823f78199 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<R, C> {
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 973a4675621..6a6ff96e83d 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 2e3b749a152..914b5ccd683 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 71f02449d3b..1837acc4bab 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 1ac00102094..b5d4d177e89 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 828de6cbe41..c5ff6d36a13 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'));"
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]