[feature](function) support ip function ipv6numtostring(alias inet6_ntoa) (#27342)

This commit is contained in:
Chester
2023-12-02 11:48:19 +08:00
committed by GitHub
parent 54b5d04ff9
commit 2e1ce758f1
17 changed files with 673 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"
]
},
{

View File

@ -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

View File

@ -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

View File

@ -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"),

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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": [

View File

@ -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

View File

@ -20,4 +20,58 @@
0
-- !sql --
3232235521
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

View File

@ -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'));"
}

View File

@ -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'));"
}