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 2e1ce758f18 [feature](function) support ip function
ipv6numtostring(alias inet6_ntoa) (#27342)
2e1ce758f18 is described below
commit 2e1ce758f181ebc0e5f921beaf30306f4e49519c
Author: Chester <[email protected]>
AuthorDate: Sat Dec 2 11:48:19 2023 +0800
[feature](function) support ip function ipv6numtostring(alias inet6_ntoa)
(#27342)
---
be/src/vec/common/format_ip.cpp | 116 +++++++++++++++++++++
be/src/vec/common/format_ip.h | 7 ++
be/src/vec/functions/function_ip.cpp | 2 +
be/src/vec/functions/function_ip.h | 98 +++++++++++++++++
.../sql-functions/ip-functions/inet6-ntoa.md | 56 ++++++++++
.../ip-functions/ipv6-num-to-string.md | 56 ++++++++++
docs/sidebars.json | 4 +-
.../sql-functions/ip-functions/inet6-ntoa.md | 56 ++++++++++
.../ip-functions/ipv6-num-to-string.md | 56 ++++++++++
.../doris/catalog/BuiltinScalarFunctions.java | 2 +
.../functions/scalar/Ipv6NumToString.java | 66 ++++++++++++
.../expressions/visitor/ScalarFunctionVisitor.java | 5 +
gensrc/script/doris_builtins_functions.py | 4 +-
.../data/nereids_function_p0/ip_functions.out | 54 ++++++++++
.../ip_functions/test_ip_functions.out | 56 +++++++++-
.../suites/nereids_function_p0/ip_functions.groovy | 19 ++++
.../ip_functions/test_ip_functions.groovy | 19 ++++
17 files changed, 673 insertions(+), 3 deletions(-)
diff --git a/be/src/vec/common/format_ip.cpp b/be/src/vec/common/format_ip.cpp
index 1ad0e6899b1..b673d5575dd 100644
--- a/be/src/vec/common/format_ip.cpp
+++ b/be/src/vec/common/format_ip.cpp
@@ -23,6 +23,7 @@
#include <algorithm>
#include <array>
+#include "vec/common/hex.h"
#include "vec/core/types.h"
namespace doris::vectorized {
@@ -75,4 +76,119 @@ consteval std::array<std::pair<const char*, size_t>, N>
str_make_array() {
/// This will generate static array of pair<const char *, size_t> for [0..255]
at compile time
extern constexpr std::array<std::pair<const char*, size_t>, 256>
one_byte_to_string_lookup_table =
str_make_array<256>();
+
+/// integer logarithm, return ceil(log(value, base)) (the smallest integer
greater or equal than log(value, base)
+static constexpr UInt32 intLog(const UInt32 value, const UInt32 base, const
bool carry) {
+ return value >= base ? 1 + intLog(value / base, base, value % base ||
carry)
+ : value % base > 1 || carry;
+}
+
+/// Print integer in desired base, faster than sprintf.
+/// NOTE This is not the best way. See
https://github.com/miloyip/itoa-benchmark
+/// But it doesn't matter here.
+template <UInt32 base, typename T>
+static void print_integer(char*& out, T value) {
+ if (value == 0) {
+ *out++ = '0';
+ } else {
+ constexpr size_t buffer_size = sizeof(T) * intLog(256, base, false);
+
+ char buf[buffer_size];
+ auto ptr = buf;
+
+ while (value > 0) {
+ *ptr = hex_digit_lowercase(value % base);
+ ++ptr;
+ value /= base;
+ }
+
+ /// Copy to out reversed.
+ while (ptr != buf) {
+ --ptr;
+ *out = *ptr;
+ ++out;
+ }
+ }
+}
+
+void formatIPv6(const unsigned char* src, char*& dst, uint8_t
zeroed_tail_bytes_count) {
+ struct {
+ Int64 base, len;
+ } best {-1, 0}, cur {-1, 0};
+ std::array<UInt16, IPV6_BINARY_LENGTH / sizeof(UInt16)> words {};
+
+ /** Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding. */
+ for (size_t i = 0; i < (IPV6_BINARY_LENGTH - zeroed_tail_bytes_count); i
+= 2) {
+ words[i / 2] = (src[i] << 8) | src[i + 1];
+ }
+
+ for (size_t i = 0; i < words.size(); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1) {
+ cur.base = i;
+ cur.len = 1;
+ } else {
+ cur.len++;
+ }
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len) {
+ best = cur;
+ }
+ cur.base = -1;
+ }
+ }
+ }
+
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len) {
+ best = cur;
+ }
+ }
+ if (best.base != -1 && best.len < 2) {
+ best.base = -1;
+ }
+
+ /// Format the result.
+ for (size_t i = 0; i < words.size(); i++) {
+ /// Are we inside the best run of 0x00's?
+ if (best.base != -1) {
+ auto best_base = static_cast<size_t>(best.base);
+ if (i >= best_base && i < (best_base + best.len)) {
+ if (i == best_base) {
+ *dst++ = ':';
+ }
+ continue;
+ }
+ }
+ /// Are we following an initial run of 0x00s or any real hex?
+ if (i != 0) {
+ *dst++ = ':';
+ }
+ /// Is this address an encapsulated IPv4?
+ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 &&
words[5] == 0xffffu))) {
+ uint8_t ipv4_buffer[IPV4_BINARY_LENGTH] = {0};
+ memcpy(ipv4_buffer, src + 12, IPV4_BINARY_LENGTH);
+ // Due to historical reasons formatIPv4() takes ipv4 in BE format,
but inside ipv6 we store it in LE-format.
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ std::reverse(std::begin(ipv4_buffer), std::end(ipv4_buffer));
+#endif
+ formatIPv4(ipv4_buffer, dst,
+ std::min(zeroed_tail_bytes_count,
static_cast<uint8_t>(IPV4_BINARY_LENGTH)),
+ "0");
+ // formatIPv4 has already added a null-terminator for us.
+ return;
+ }
+ print_integer<16>(dst, words[i]);
+ }
+
+ /// Was it a trailing run of 0x00's?
+ if (best.base != -1 &&
+ static_cast<size_t>(best.base) + static_cast<size_t>(best.len) ==
words.size()) {
+ *dst++ = ':';
+ }
+}
+
} // namespace doris::vectorized
diff --git a/be/src/vec/common/format_ip.h b/be/src/vec/common/format_ip.h
index ff440b11e21..ab9ac4b6595 100644
--- a/be/src/vec/common/format_ip.h
+++ b/be/src/vec/common/format_ip.h
@@ -37,6 +37,7 @@ constexpr size_t IPV4_MAX_NUM_VALUE = 4294967295; //num value
of '255.255.255.25
constexpr int IPV4_MAX_OCTET_VALUE = 255; //max vulue of octet
constexpr size_t IPV4_OCTET_BITS = 8;
constexpr size_t DECIMAL_BASE = 10;
+constexpr size_t IPV6_BINARY_LENGTH = 16;
namespace doris::vectorized {
@@ -191,4 +192,10 @@ inline bool parseIPv4whole(const char* src, unsigned char*
dst) {
return end != nullptr && *end == '\0';
}
+/** Rewritten inet_ntop6 from
http://svn.apache.org/repos/asf/apr/apr/trunk/network_io/unix/inet_pton.c
+ * performs significantly faster than the reference implementation due to
the absence of sprintf calls,
+ * bounds checking, unnecessary string copying and length calculation.
+ */
+void formatIPv6(const unsigned char* src, char*& dst, uint8_t
zeroed_tail_bytes_count = 0);
+
} // namespace doris::vectorized
diff --git a/be/src/vec/functions/function_ip.cpp
b/be/src/vec/functions/function_ip.cpp
index 762134780db..643c69939d3 100644
--- a/be/src/vec/functions/function_ip.cpp
+++ b/be/src/vec/functions/function_ip.cpp
@@ -30,5 +30,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");
}
} // namespace doris::vectorized
\ No newline at end of file
diff --git a/be/src/vec/functions/function_ip.h
b/be/src/vec/functions/function_ip.h
index 18ffc655eb8..4a39242e85e 100644
--- a/be/src/vec/functions/function_ip.h
+++ b/be/src/vec/functions/function_ip.h
@@ -26,9 +26,11 @@
#include "vec/columns/column_vector.h"
#include "vec/common/format_ip.h"
#include "vec/core/column_with_type_and_name.h"
+#include "vec/data_types/data_type_ipv6.h"
#include "vec/data_types/data_type_number.h"
#include "vec/data_types/data_type_string.h"
#include "vec/functions/function.h"
+#include "vec/functions/function_helpers.h"
#include "vec/functions/simple_function_factory.h"
namespace doris::vectorized {
@@ -250,4 +252,100 @@ public:
}
};
+template <typename T>
+void process_ipv6_column(const ColumnPtr& column, size_t input_rows_count,
+ ColumnString::Chars& vec_res, ColumnString::Offsets&
offsets_res,
+ ColumnUInt8::MutablePtr& null_map, unsigned char*
ipv6_address_data) {
+ auto* begin = reinterpret_cast<char*>(vec_res.data());
+ auto* pos = begin;
+
+ const auto* col = check_and_get_column<T>(column.get());
+
+ for (size_t i = 0; i < input_rows_count; ++i) {
+ bool is_empty = false;
+
+ if constexpr (std::is_same_v<T, ColumnIPv6>) {
+ const auto& vec_in = col->get_data();
+ memcpy(ipv6_address_data, reinterpret_cast<const unsigned
char*>(&vec_in[i]),
+ IPV6_BINARY_LENGTH);
+ } else {
+ const auto str_ref = col->get_data_at(i);
+ const char* value = str_ref.data;
+ size_t value_size = str_ref.size;
+
+ if (value_size > IPV6_BINARY_LENGTH || value == nullptr ||
value_size == 0) {
+ is_empty = true;
+ } else {
+ memcpy(ipv6_address_data, value, value_size);
+ memset(ipv6_address_data + value_size, 0, IPV6_BINARY_LENGTH -
value_size);
+ }
+ }
+
+ if (is_empty) {
+ offsets_res[i] = pos - begin;
+ null_map->get_data()[i] = 1;
+ } else {
+ formatIPv6(ipv6_address_data, pos);
+ offsets_res[i] = pos - begin;
+ }
+ }
+}
+
+class FunctionIPv6NumToString : public IFunction {
+public:
+ static constexpr auto name = "ipv6numtostring";
+ static FunctionPtr create() { return
std::make_shared<FunctionIPv6NumToString>(); }
+
+ 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 {
+ const auto* arg_string =
check_and_get_data_type<DataTypeString>(arguments[0].get());
+ const auto* arg_ipv6 =
check_and_get_data_type<DataTypeIPv6>(arguments[0].get());
+ if (!arg_ipv6 && !(arg_string))
+ throw Exception(ErrorCode::INVALID_ARGUMENT,
+ "Illegal type {} of argument of function {},
expected IPv6 or String",
+ arguments[0]->get_name(), get_name());
+
+ return make_nullable(std::make_shared<DataTypeString>());
+ }
+
+ bool use_default_implementation_for_nulls() const override { return true; }
+
+ 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_ipv6 = check_and_get_column<ColumnIPv6>(column.get());
+ const auto* col_string =
check_and_get_column<ColumnString>(column.get());
+
+ if (!col_ipv6 && !col_string)
+ throw Exception(ErrorCode::INVALID_ARGUMENT,
+ "Illegal column {} of argument of function {},
expected IPv6 or String",
+ column->get_name(), get_name());
+
+ auto col_res = ColumnString::create();
+ ColumnString::Chars& vec_res = col_res->get_chars();
+ ColumnString::Offsets& offsets_res = col_res->get_offsets();
+ vec_res.resize(input_rows_count * (IPV6_MAX_TEXT_LENGTH + 1));
+ offsets_res.resize(input_rows_count);
+
+ auto null_map = ColumnUInt8::create(input_rows_count, 0);
+
+ unsigned char ipv6_address_data[IPV6_BINARY_LENGTH];
+
+ if (col_ipv6) {
+ process_ipv6_column<ColumnIPv6>(column, input_rows_count, vec_res,
offsets_res,
+ null_map, ipv6_address_data);
+ } else {
+ process_ipv6_column<ColumnString>(column, input_rows_count,
vec_res, offsets_res,
+ null_map, ipv6_address_data);
+ }
+
+ block.replace_by_position(result,
+ ColumnNullable::create(std::move(col_res),
std::move(null_map)));
+ return Status::OK();
+ }
+};
+
} // namespace doris::vectorized
\ No newline at end of file
diff --git a/docs/en/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
b/docs/en/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
new file mode 100644
index 00000000000..638800ec44e
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
@@ -0,0 +1,56 @@
+---
+{
+"title": "INET6_NTOA",
+"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.
+-->
+
+## INET6_NTOA
+
+<version since="dev">
+
+INET6_NTOA
+
+</version>
+
+### description
+
+#### Syntax
+
+`VARCHAR INET6_NTOA(VARCHAR ipv6_num)`
+
+Takes an IPv6 address in binary format of type String. Returns the string of
this address in text format.
+The IPv4 address mapped by IPv6 starts with ::ffff:111.222.33.
+
+### example
+
+```
+mysql> select inet6_ntoa(unhex('2A0206B8000000000000000000000011')) as addr;
++--------------+
+| addr |
++--------------+
+| 2a02:6b8::11 |
++--------------+
+1 row in set (0.01 sec)
+```
+
+### keywords
+
+INET6_NTOA, IP
\ No newline at end of file
diff --git
a/docs/en/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
b/docs/en/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
new file mode 100644
index 00000000000..96941771ecd
--- /dev/null
+++ b/docs/en/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
@@ -0,0 +1,56 @@
+---
+{
+"title": "IPV6_NUM_TO_STRING",
+"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.
+-->
+
+## IPv6NumToString
+
+<version since="dev">
+
+IPv6NumToString
+
+</version>
+
+### description
+
+#### Syntax
+
+`VARCHAR IPv6NumToString(VARCHAR ipv6_num)`
+
+Takes an IPv6 address in binary format of type String. Returns the string of
this address in text format.
+The IPv4 address mapped by IPv6 starts with ::ffff:111.222.33.
+
+### example
+
+```
+mysql> select ipv6numtostring(unhex('2A0206B8000000000000000000000011')) as
addr;
++--------------+
+| addr |
++--------------+
+| 2a02:6b8::11 |
++--------------+
+1 row in set (0.01 sec)
+```
+
+### keywords
+
+IPV6NUMTOSTRING, IP
diff --git a/docs/sidebars.json b/docs/sidebars.json
index 2efc051f686..4db8f541361 100644
--- a/docs/sidebars.json
+++ b/docs/sidebars.json
@@ -785,7 +785,9 @@
"sql-manual/sql-functions/ip-functions/ipv4-string-to-num",
"sql-manual/sql-functions/ip-functions/inet-aton",
"sql-manual/sql-functions/ip-functions/ipv4-string-to-num-or-default",
-
"sql-manual/sql-functions/ip-functions/ipv4-string-to-num-or-null"
+
"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"
]
},
{
diff --git
a/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
new file mode 100644
index 00000000000..aaeb3cc0c32
--- /dev/null
+++ b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/inet6-ntoa.md
@@ -0,0 +1,56 @@
+---
+{
+"title": "INET6_NTOA",
+"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.
+-->
+
+## INET6_NTOA
+
+<version since="dev">
+
+INET6_NTOA
+
+</version>
+
+### description
+
+#### Syntax
+
+`VARCHAR INET6_NTOA(VARCHAR ipv6_num)`
+
+接受字符串类型的二进制格式的IPv6地址。以文本格式返回此地址的字符串。
+IPv6映射的IPv4地址以::ffff:111.222.33。
+
+### example
+
+```
+mysql> select inet6_ntoa(unhex('2A0206B8000000000000000000000011')) as addr;
++--------------+
+| addr |
++--------------+
+| 2a02:6b8::11 |
++--------------+
+1 row in set (0.01 sec)
+```
+
+### keywords
+
+INET6_NTOA, IP
\ No newline at end of file
diff --git
a/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
new file mode 100644
index 00000000000..c58ecf42f4c
--- /dev/null
+++
b/docs/zh-CN/docs/sql-manual/sql-functions/ip-functions/ipv6-num-to-string.md
@@ -0,0 +1,56 @@
+---
+{
+"title": "IPV6_NUM_TO_STRING",
+"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.
+-->
+
+## IPv6NumToString
+
+<version since="dev">
+
+IPv6NumToString
+
+</version>
+
+### description
+
+#### Syntax
+
+`VARCHAR IPv6NumToString(VARCHAR ipv6_num)`
+
+接受字符串类型的二进制格式的IPv6地址。以文本格式返回此地址的字符串。
+IPv6映射的IPv4地址以::ffff:111.222.33。
+
+### example
+
+```
+mysql> select ipv6numtostring(unhex('2A0206B8000000000000000000000011')) as
addr;
++--------------+
+| addr |
++--------------+
+| 2a02:6b8::11 |
++--------------+
+1 row in set (0.01 sec)
+```
+
+### keywords
+
+IPV6NUMTOSTRING, IP
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 5df7b67d36b..ee646e58ed3 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
@@ -193,6 +193,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4NumToStri
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNum;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrDefault;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrNull;
+import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6NumToString;
import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonArray;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.JsonContains;
import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonExtract;
@@ -588,6 +589,7 @@ public class BuiltinScalarFunctions implements
FunctionHelper {
scalar(Ipv4StringToNum.class, "ipv4stringtonum", "inet_aton"),
scalar(Ipv4StringToNumOrDefault.class, "ipv4stringtonumordefault"),
scalar(Ipv4StringToNumOrNull.class, "ipv4stringtonumornull"),
+ scalar(Ipv6NumToString.class, "ipv6numtostring", "inet6_ntoa"),
scalar(JsonArray.class, "json_array"),
scalar(JsonObject.class, "json_object"),
scalar(JsonQuote.class, "json_quote"),
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Ipv6NumToString.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Ipv6NumToString.java
new file mode 100644
index 00000000000..fafd3fe7a46
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Ipv6NumToString.java
@@ -0,0 +1,66 @@
+// 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.AlwaysNullable;
+import
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+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 Ipv6NumToString
+ */
+public class Ipv6NumToString extends ScalarFunction
+ implements BinaryExpression, ExplicitlyCastableSignature,
AlwaysNullable {
+
+ public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
+
FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(VarcharType.SYSTEM_DEFAULT),
+
FunctionSignature.ret(StringType.INSTANCE).args(StringType.INSTANCE));
+
+ public Ipv6NumToString(Expression arg0) {
+ super("ipv6numtostring", arg0);
+ }
+
+ @Override
+ public Ipv6NumToString withChildren(List<Expression> children) {
+ Preconditions.checkArgument(children.size() == 1,
+ "ipv6numtostring accept 1 args, but got %s (%s)",
+ children.size(),
+ children);
+ return new Ipv6NumToString(children.get(0));
+ }
+
+ @Override
+ public List<FunctionSignature> getSignatures() {
+ return SIGNATURES;
+ }
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+ return visitor.visitIpv6NumToString(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 20ba455a65b..aab82b48bcb 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
@@ -189,6 +189,7 @@ import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4NumToStri
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNum;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrDefault;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrNull;
+import
org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6NumToString;
import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonArray;
import
org.apache.doris.nereids.trees.expressions.functions.scalar.JsonContains;
import org.apache.doris.nereids.trees.expressions.functions.scalar.JsonExtract;
@@ -1111,6 +1112,10 @@ public interface ScalarFunctionVisitor<R, C> {
return visitScalarFunction(ipv4StringToNumOrNull, context);
}
+ default R visitIpv6NumToString(Ipv6NumToString ipv6NumToString, C context)
{
+ return visitScalarFunction(ipv6NumToString, context);
+ }
+
default R visitJsonArray(JsonArray jsonArray, C context) {
return visitScalarFunction(jsonArray, context);
}
diff --git a/gensrc/script/doris_builtins_functions.py
b/gensrc/script/doris_builtins_functions.py
index d7eff94f803..ea72795d085 100644
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -2010,7 +2010,9 @@ visible_functions = {
[['ipv4stringtonumordefault'], 'BIGINT', ['VARCHAR'],
'ALWAYS_NOT_NULLABLE'],
[['ipv4stringtonumordefault'], 'BIGINT', ['STRING'],
'ALWAYS_NOT_NULLABLE'],
[['ipv4stringtonumornull'], 'BIGINT', ['VARCHAR'], 'ALWAYS_NULLABLE'],
- [['ipv4stringtonumornull'], 'BIGINT', ['STRING'], 'ALWAYS_NULLABLE'],
+ [['ipv4stringtonumornull'], 'BIGINT', ['STRING'], 'ALWAYS_NULLABLE'],
+ [['ipv6numtostring','inet6_ntoa'], 'VARCHAR', ['VARCHAR'],
'ALWAYS_NULLABLE'],
+ [['ipv6numtostring','inet6_ntoa'], 'STRING', ['STRING'],
'ALWAYS_NULLABLE'],
],
"NonNullalbe": [
diff --git a/regression-test/data/nereids_function_p0/ip_functions.out
b/regression-test/data/nereids_function_p0/ip_functions.out
index 8a3254a993b..f906ee221f0 100644
--- a/regression-test/data/nereids_function_p0/ip_functions.out
+++ b/regression-test/data/nereids_function_p0/ip_functions.out
@@ -34,3 +34,57 @@
-- !ip12 --
3232235521
+
+-- !ip13 --
+\N
+
+-- !ip14 --
+2a02:6b8::11
+
+-- !ip15 --
+fdfe::5a55:caff:fefa:9089
+
+-- !ip16 --
+\N
+
+-- !ip17 --
+\N
+
+-- !ip18 --
+a00:509::
+
+-- !ip19 --
+abcd:1234:5600::
+
+-- !ip20 --
+\N
+
+-- !ip21 --
+\N
+
+-- !ip22 --
+2a02:6b8::11
+
+-- !ip23 --
+\N
+
+-- !ip24 --
+::
+
+-- !ip25 --
+::
+
+-- !ip26 --
+\N
+
+-- !ip27 --
+aaaa:aaaa:ffff:ffff:ffff:ffff:aaaa:aaaa
+
+-- !ip28 --
+\N
+
+-- !ip29 --
+\N
+
+-- !ip30 --
+::ffff:127.0.0.1
\ 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 5005a68cd46..54e2fac8892 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
@@ -20,4 +20,58 @@
0
-- !sql --
-3232235521
\ No newline at end of file
+3232235521
+
+-- !sql --
+\N
+
+-- !sql --
+2a02:6b8::11
+
+-- !sql --
+fdfe::5a55:caff:fefa:9089
+
+-- !sql --
+\N
+
+-- !sql --
+\N
+
+-- !sql --
+a00:509::
+
+-- !sql --
+abcd:1234:5600::
+
+-- !sql --
+\N
+
+-- !sql --
+\N
+
+-- !sql --
+2a02:6b8::11
+
+-- !sql --
+\N
+
+-- !sql --
+::
+
+-- !sql --
+::
+
+-- !sql --
+\N
+
+-- !sql --
+aaaa:aaaa:ffff:ffff:ffff:ffff:aaaa:aaaa
+
+-- !sql --
+\N
+
+-- !sql --
+\N
+
+-- !sql --
+::ffff:127.0.0.1
\ 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 5b0588e8fdd..2a6f8caad6c 100644
--- a/regression-test/suites/nereids_function_p0/ip_functions.groovy
+++ b/regression-test/suites/nereids_function_p0/ip_functions.groovy
@@ -31,4 +31,23 @@ suite("ip_functions") {
qt_ip10 "SELECT ipv4stringtonumornull('');"
qt_ip11 "SELECT ipv4stringtonumordefault('');"
qt_ip12 "SELECT inet_aton('192.168.0.1');"
+
+ qt_ip13 "SELECT ipv6numtostring(unhex('0A0005091'));"
+ qt_ip14 "SELECT
ipv6numtostring(unhex('2A0206B8000000000000000000000011'));"
+ qt_ip15 "SELECT
ipv6numtostring(unhex('FDFE0000000000005A55CAFFFEFA9089'));"
+ qt_ip16 "SELECT ipv6numtostring(unhex(''));"
+ qt_ip17 "SELECT ipv6numtostring(unhex('KK'));"
+ qt_ip18 "SELECT ipv6numtostring(unhex('0A000509'));"
+ qt_ip19 "SELECT ipv6numtostring(unhex('abcd123456'));"
+ qt_ip20 "SELECT
ipv6numtostring(unhex('ffffffffffffffffffffffffffffffffffffffffffffffffffffff'));"
+ qt_ip21 "SELECT inet6_ntoa(unhex('0A0005091'));"
+ qt_ip22 "SELECT inet6_ntoa(unhex('2A0206B8000000000000000000000011'));"
+ qt_ip23 "SELECT inet6_ntoa(unhex(NULL));"
+ qt_ip24 "SELECT inet6_ntoa(unhex('00000000000000000000000000000000'));"
+ qt_ip25 "SELECT inet6_ntoa(unhex('0000000000000000000000000000'));"
+ qt_ip26 "SELECT inet6_ntoa(unhex('000'));"
+ qt_ip27 "SELECT inet6_ntoa(unhex('aaaaaaaaFFFFFFFFFFFFFFFFaaaaaaaa'));"
+ qt_ip28 "SELECT inet6_ntoa(unhex('aaaa@#'));"
+ qt_ip29 "SELECT inet6_ntoa(unhex('\0'));"
+ qt_ip30 "SELECT inet6_ntoa(unhex('00000000000000000000FFFF7F000001'));"
}
\ 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 5d222f544a2..6991da94c26 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
@@ -26,4 +26,23 @@ suite("test_ip_functions") {
qt_sql "SELECT ipv4stringtonumornull('');"
qt_sql "SELECT ipv4stringtonumordefault('');"
qt_sql "SELECT inet_aton('192.168.0.1');"
+
+ qt_sql "SELECT ipv6numtostring(unhex('0A0005091'));"
+ qt_sql "SELECT ipv6numtostring(unhex('2A0206B8000000000000000000000011'));"
+ qt_sql "SELECT ipv6numtostring(unhex('FDFE0000000000005A55CAFFFEFA9089'));"
+ qt_sql "SELECT ipv6numtostring(unhex(''));"
+ qt_sql "SELECT ipv6numtostring(unhex('KK'));"
+ qt_sql "SELECT ipv6numtostring(unhex('0A000509'));"
+ qt_sql "SELECT ipv6numtostring(unhex('abcd123456'));"
+ qt_sql "SELECT
ipv6numtostring(unhex('ffffffffffffffffffffffffffffffffffffffffffffffffffffff'));"
+ qt_sql "SELECT inet6_ntoa(unhex('0A0005091'));"
+ qt_sql "SELECT inet6_ntoa(unhex('2A0206B8000000000000000000000011'));"
+ qt_sql "SELECT inet6_ntoa(unhex(NULL));"
+ qt_sql "SELECT inet6_ntoa(unhex('00000000000000000000000000000000'));"
+ qt_sql "SELECT inet6_ntoa(unhex('0000000000000000000000000000'));"
+ qt_sql "SELECT inet6_ntoa(unhex('000'));"
+ qt_sql "SELECT inet6_ntoa(unhex('aaaaaaaaFFFFFFFFFFFFFFFFaaaaaaaa'));"
+ qt_sql "SELECT inet6_ntoa(unhex('aaaa@#'));"
+ qt_sql "SELECT inet6_ntoa(unhex('\0'));"
+ qt_sql "SELECT inet6_ntoa(unhex('00000000000000000000FFFF7F000001'));"
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]