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]

Reply via email to