This is an automated email from the ASF dual-hosted git repository.
panxiaolei 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 ce0e987adbe [refine](cast) Use the new cast to implement cast to ip
(#53722)
ce0e987adbe is described below
commit ce0e987adbeb536575d3c6a4b5589a4744057c58
Author: Mryange <[email protected]>
AuthorDate: Mon Jul 28 15:39:29 2025 +0800
[refine](cast) Use the new cast to implement cast to ip (#53722)
https://github.com/apache/doris-website/pull/2653
---
be/src/vec/common/format_ip.h | 9 +
.../vec/data_types/serde/data_type_ipv4_serde.cpp | 40 +++
be/src/vec/data_types/serde/data_type_ipv4_serde.h | 7 +
.../vec/data_types/serde/data_type_ipv6_serde.cpp | 40 +++
be/src/vec/data_types/serde/data_type_ipv6_serde.h | 7 +
be/src/vec/functions/cast/cast_to_ip.h | 127 ++++------
be/test/vec/function/cast/cast_to_ip_test.cpp | 277 +++++++++++++++++++++
be/test/vec/function/function_test_util.h | 2 +
.../doris/nereids/trees/expressions/Cast.java | 3 +-
.../data/function_p0/cast/test_cast_to_ip.out | Bin 0 -> 1169 bytes
.../nereids_function_p0/fn_test_ip_invalid.csv | 8 +-
.../suites/datatype_p0/ip/test_ip_crud.groovy | 2 +-
.../datatype_p0/ip/test_ip_implicit_cast.groovy | 8 +-
.../suites/function_p0/cast/test_cast_to_ip.groovy | 198 +++++++++++++++
.../nereids_p0/javaudf/test_javaudf_ip.groovy | 4 +-
.../suites/query_p0/aggregate/array_agg.groovy | 4 +-
.../suites/statistics/test_analyze_ip_type.groovy | 8 +-
17 files changed, 644 insertions(+), 100 deletions(-)
diff --git a/be/src/vec/common/format_ip.h b/be/src/vec/common/format_ip.h
index 365b182161a..3b6a5483998 100644
--- a/be/src/vec/common/format_ip.h
+++ b/be/src/vec/common/format_ip.h
@@ -379,6 +379,10 @@ inline bool parse_ipv6(T*& src, EOFfunction eof, unsigned
char* dst, int32_t fir
return clear_dst();
zptr = iter;
++src;
+ if (!eof() && *src == ':') {
+ /// more than one all-zeroes block is not allowed
+ return clear_dst();
+ }
continue;
}
if (groups == 0) /// leading colon is not allowed
@@ -446,6 +450,11 @@ inline bool parse_ipv6(T*& src, EOFfunction eof, unsigned
char* dst, int32_t fir
/// process all-zeroes block
if (zptr != nullptr) {
+ if (groups == 8) {
+ /// all-zeroes block at least should be one
+ /// 2001:0db8:86a3::08d3:1319:8a2e:0370:7344 not valid
+ return clear_dst();
+ }
size_t msize = iter - zptr;
std::memmove(dst + IPV6_BINARY_LENGTH - msize, zptr, msize);
std::memset(zptr, '\0', IPV6_BINARY_LENGTH - (iter - dst));
diff --git a/be/src/vec/data_types/serde/data_type_ipv4_serde.cpp
b/be/src/vec/data_types/serde/data_type_ipv4_serde.cpp
index 463c91f6dcd..db318afc3fe 100644
--- a/be/src/vec/data_types/serde/data_type_ipv4_serde.cpp
+++ b/be/src/vec/data_types/serde/data_type_ipv4_serde.cpp
@@ -21,6 +21,7 @@
#include "vec/columns/column_const.h"
#include "vec/core/types.h"
+#include "vec/functions/cast/cast_to_ip.h"
#include "vec/io/io_helper.h"
namespace doris::vectorized {
@@ -148,4 +149,43 @@ Status DataTypeIPv4SerDe::read_column_from_arrow(IColumn&
column, const arrow::A
col_data.insert(raw_data, raw_data + row_count);
return Status::OK();
}
+
+Status DataTypeIPv4SerDe::from_string_batch(const ColumnString& str,
ColumnNullable& column,
+ const FormatOptions& options)
const {
+ const auto size = str.size();
+ column.resize(size);
+
+ auto& column_to = assert_cast<ColumnType&>(column.get_nested_column());
+ auto& vec_to = column_to.get_data();
+ auto& null_map = column.get_null_map_data();
+
+ CastParameters params;
+ params.is_strict = false;
+ for (size_t i = 0; i < size; ++i) {
+ null_map[i] = !CastToIPv4::from_string(str.get_data_at(i), vec_to[i],
params);
+ }
+ return Status::OK();
+}
+
+Status DataTypeIPv4SerDe::from_string_strict_mode_batch(const ColumnString&
str, IColumn& column,
+ const FormatOptions&
options,
+ const
NullMap::value_type* null_map) const {
+ const auto size = str.size();
+ column.resize(size);
+
+ auto& column_to = assert_cast<ColumnType&>(column);
+ auto& vec_to = column_to.get_data();
+ CastParameters params;
+ params.is_strict = true;
+ for (size_t i = 0; i < size; ++i) {
+ if (null_map && null_map[i]) {
+ continue;
+ }
+ if (!CastToIPv4::from_string(str.get_data_at(i), vec_to[i], params)) {
+ return Status::InvalidArgument("parse ipv4 fail, string: '{}'",
+ str.get_data_at(i).to_string());
+ }
+ }
+ return Status::OK();
+}
} // namespace doris::vectorized
diff --git a/be/src/vec/data_types/serde/data_type_ipv4_serde.h
b/be/src/vec/data_types/serde/data_type_ipv4_serde.h
index 24cc66f4646..eb7505feea2 100644
--- a/be/src/vec/data_types/serde/data_type_ipv4_serde.h
+++ b/be/src/vec/data_types/serde/data_type_ipv4_serde.h
@@ -59,6 +59,13 @@ public:
Status read_column_from_arrow(IColumn& column, const arrow::Array*
arrow_array, int64_t start,
int64_t end, const cctz::time_zone& ctz)
const override;
+ Status from_string_batch(const ColumnString& str, ColumnNullable& column,
+ const FormatOptions& options) const override;
+
+ Status from_string_strict_mode_batch(
+ const ColumnString& str, IColumn& column, const FormatOptions&
options,
+ const NullMap::value_type* null_map = nullptr) const override;
+
private:
template <bool is_binary_format>
Status _write_column_to_mysql(const IColumn& column,
MysqlRowBuffer<is_binary_format>& result,
diff --git a/be/src/vec/data_types/serde/data_type_ipv6_serde.cpp
b/be/src/vec/data_types/serde/data_type_ipv6_serde.cpp
index 656897f3095..537006464cf 100644
--- a/be/src/vec/data_types/serde/data_type_ipv6_serde.cpp
+++ b/be/src/vec/data_types/serde/data_type_ipv6_serde.cpp
@@ -25,6 +25,7 @@
#include "util/jsonb_writer.h"
#include "vec/columns/column_const.h"
#include "vec/core/types.h"
+#include "vec/functions/cast/cast_to_ip.h"
#include "vec/io/io_helper.h"
namespace doris::vectorized {
@@ -250,4 +251,43 @@ Status DataTypeIPv6SerDe::write_column_to_orc(const
std::string& timezone, const
return Status::OK();
}
+Status DataTypeIPv6SerDe::from_string_batch(const ColumnString& str,
ColumnNullable& column,
+ const FormatOptions& options)
const {
+ const auto size = str.size();
+ column.resize(size);
+
+ auto& column_to = assert_cast<ColumnType&>(column.get_nested_column());
+ auto& vec_to = column_to.get_data();
+ auto& null_map = column.get_null_map_data();
+
+ CastParameters params;
+ params.is_strict = false;
+ for (size_t i = 0; i < size; ++i) {
+ null_map[i] = !CastToIPv6::from_string(str.get_data_at(i), vec_to[i],
params);
+ }
+ return Status::OK();
+}
+
+Status DataTypeIPv6SerDe::from_string_strict_mode_batch(const ColumnString&
str, IColumn& column,
+ const FormatOptions&
options,
+ const
NullMap::value_type* null_map) const {
+ const auto size = str.size();
+ column.resize(size);
+
+ auto& column_to = assert_cast<ColumnType&>(column);
+ auto& vec_to = column_to.get_data();
+ CastParameters params;
+ params.is_strict = true;
+ for (size_t i = 0; i < size; ++i) {
+ if (null_map && null_map[i]) {
+ continue;
+ }
+ if (!CastToIPv6::from_string(str.get_data_at(i), vec_to[i], params)) {
+ return Status::InvalidArgument("parse ipv6 fail, string: '{}'",
+ str.get_data_at(i).to_string());
+ }
+ }
+ return Status::OK();
+}
+
} // namespace doris::vectorized
diff --git a/be/src/vec/data_types/serde/data_type_ipv6_serde.h
b/be/src/vec/data_types/serde/data_type_ipv6_serde.h
index 85e2f8167fb..1c586025a22 100644
--- a/be/src/vec/data_types/serde/data_type_ipv6_serde.h
+++ b/be/src/vec/data_types/serde/data_type_ipv6_serde.h
@@ -69,6 +69,13 @@ public:
void write_one_cell_to_jsonb(const IColumn& column,
JsonbWriterT<JsonbOutStream>& result,
Arena& mem_pool, int unique_id, int64_t
row_num) const override;
+ Status from_string_batch(const ColumnString& str, ColumnNullable& column,
+ const FormatOptions& options) const override;
+
+ Status from_string_strict_mode_batch(
+ const ColumnString& str, IColumn& column, const FormatOptions&
options,
+ const NullMap::value_type* null_map = nullptr) const override;
+
private:
template <bool is_binary_format>
Status _write_column_to_mysql(const IColumn& column,
MysqlRowBuffer<is_binary_format>& result,
diff --git a/be/src/vec/functions/cast/cast_to_ip.h
b/be/src/vec/functions/cast/cast_to_ip.h
index fd447bd1032..c953830b54d 100644
--- a/be/src/vec/functions/cast/cast_to_ip.h
+++ b/be/src/vec/functions/cast/cast_to_ip.h
@@ -25,36 +25,31 @@
namespace doris::vectorized {
#include "common/compile_check_begin.h"
-template <CastModeType AllMode>
-class CastToImpl<AllMode, DataTypeString, DataTypeIPv4> : public CastToBase {
-public:
- Status execute_impl(FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
- uint32_t result, size_t input_rows_count,
- const NullMap::value_type* null_map = nullptr) const
override {
- const auto* col_from =
check_and_get_column<DataTypeString::ColumnType>(
- block.get_by_position(arguments[0]).column.get());
-
- const auto size = col_from->size();
+struct CastToIPv4 {
+ static bool from_string(const StringRef& from, IPv4& to, CastParameters&);
+};
- auto column_to = DataTypeIPv4::ColumnType::create(size);
- auto column_null_map = ColumnUInt8::create(size, 0);
+inline bool CastToIPv4::from_string(const StringRef& from, IPv4& to,
CastParameters&) {
+ return IPv4Value::from_string(to, from.data, from.size);
+}
- auto& to_data = column_to->get_data();
- auto& null_map_data = column_null_map->get_data();
+struct CastToIPv6 {
+ static bool from_string(const StringRef& from, IPv6& to, CastParameters&);
+ static bool from_ipv4(const IPv4& from, IPv6& to, CastParameters&);
+};
- for (size_t i = 0; i < size; ++i) {
- auto str = col_from->get_data_at(i);
- null_map_data[i] = !IPv4Value::from_string(to_data[i], str.data,
str.size);
- }
+inline bool CastToIPv6::from_string(const StringRef& from, IPv6& to,
CastParameters&) {
+ return IPv6Value::from_string(to, from.data, from.size);
+}
- block.get_by_position(result).column =
- ColumnNullable::create(std::move(column_to),
std::move(column_null_map));
- return Status::OK();
- }
-};
+inline bool CastToIPv6::from_ipv4(const IPv4& from, IPv6& to, CastParameters&)
{
+ map_ipv4_to_ipv6(from, reinterpret_cast<UInt8*>(&to));
+ return true;
+}
-template <CastModeType AllMode>
-class CastToImpl<AllMode, DataTypeString, DataTypeIPv6> : public CastToBase {
+template <CastModeType Mode, typename IpDataType>
+ requires(IsIPType<IpDataType>)
+class CastToImpl<Mode, DataTypeString, IpDataType> : public CastToBase {
public:
Status execute_impl(FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
uint32_t result, size_t input_rows_count,
@@ -62,21 +57,29 @@ public:
const auto* col_from =
check_and_get_column<DataTypeString::ColumnType>(
block.get_by_position(arguments[0]).column.get());
- const auto size = col_from->size();
-
- auto column_to = DataTypeIPv6::ColumnType::create(size);
- auto column_null_map = ColumnUInt8::create(size, 0);
-
- auto& to_data = column_to->get_data();
- auto& null_map_data = column_null_map->get_data();
-
- for (size_t i = 0; i < size; ++i) {
- auto str = col_from->get_data_at(i);
- null_map_data[i] = !IPv6Value::from_string(to_data[i], str.data,
str.size);
+ auto to_type = block.get_by_position(result).type;
+ auto serde = remove_nullable(to_type)->get_serde();
+ MutableColumnPtr column_to;
+
+ if constexpr (Mode == CastModeType::NonStrictMode) {
+ auto to_nullable_type = make_nullable(to_type);
+ column_to = to_nullable_type->create_column();
+ auto& nullable_col_to = assert_cast<ColumnNullable&>(*column_to);
+ RETURN_IF_ERROR(serde->from_string_batch(*col_from,
nullable_col_to, {}));
+ } else if constexpr (Mode == CastModeType::StrictMode) {
+ if (to_type->is_nullable()) {
+ return Status::InternalError(
+ "result type should be not nullable when casting
string to ip in "
+ "strict cast mode");
+ }
+ column_to = to_type->create_column();
+ RETURN_IF_ERROR(
+ serde->from_string_strict_mode_batch(*col_from,
*column_to, {}, null_map));
+ } else {
+ return Status::InternalError("Unsupported cast mode");
}
- block.get_by_position(result).column =
- ColumnNullable::create(std::move(column_to),
std::move(column_null_map));
+ block.get_by_position(result).column = std::move(column_to);
return Status::OK();
}
};
@@ -93,31 +96,11 @@ public:
auto col_to = DataTypeIPv6::ColumnType::create(size);
auto& to_data = col_to->get_data();
const auto& from_data = col_from->get_data();
+ CastParameters params;
+ params.is_strict = (AllMode == CastModeType::StrictMode);
for (size_t i = 0; i < size; ++i) {
- map_ipv4_to_ipv6(from_data[i],
reinterpret_cast<UInt8*>(&to_data[i]));
- }
-
- block.get_by_position(result).column = std::move(col_to);
- return Status::OK();
- }
-};
-
-template <CastModeType AllMode, typename OtherType>
-class CastToImpl<AllMode, OtherType, DataTypeIPv4> : public CastToBase {
-public:
- Status execute_impl(FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
- uint32_t result, size_t input_rows_count,
- const NullMap::value_type* null_map = nullptr) const
override {
- const auto* col_from = check_and_get_column<typename
OtherType::ColumnType>(
- block.get_by_position(arguments[0]).column.get());
- const auto size = col_from->size();
- auto col_to = DataTypeIPv4::ColumnType::create(size);
- auto& to_data = col_to->get_data();
- const auto& from_data = col_from->get_data();
-
- for (size_t i = 0; i < size; ++i) {
- to_data[i] = static_cast<IPv4>(from_data[i]);
+ CastToIPv6::from_ipv4(from_data[i], to_data[i], params);
}
block.get_by_position(result).column = std::move(col_to);
@@ -125,26 +108,6 @@ public:
}
};
-template <CastModeType AllMode, typename OtherType>
-class CastToImpl<AllMode, OtherType, DataTypeIPv6> : public CastToBase {
-public:
- Status execute_impl(FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
- uint32_t result, size_t input_rows_count,
- const NullMap::value_type* null_map = nullptr) const
override {
- const auto* col_from = check_and_get_column<typename
OtherType::ColumnType>(
- block.get_by_position(arguments[0]).column.get());
- const auto size = col_from->size();
- auto col_to = DataTypeIPv6::ColumnType::create(size);
- auto& to_data = col_to->get_data();
- const auto& from_data = col_from->get_data();
- for (size_t i = 0; i < size; ++i) {
- to_data[i] = static_cast<IPv6>(from_data[i]);
- }
- block.get_by_position(result).column = std::move(col_to);
- return Status::OK();
- }
-};
-
namespace CastWrapper {
template <typename IpType>
@@ -172,7 +135,7 @@ WrapperType create_ip_wrapper(FunctionContext* context,
const DataTypePtr& from_
if (!call_on_index_and_data_type<void>(from_type->get_primitive_type(),
make_ip_wrapper)) {
return create_unsupport_wrapper(
- fmt::format("CAST AS bool not supported {}",
from_type->get_name()));
+ fmt::format("CAST AS ip not supported {}",
from_type->get_name()));
}
return [cast_to_ip](FunctionContext* context, Block& block, const
ColumnNumbers& arguments,
diff --git a/be/test/vec/function/cast/cast_to_ip_test.cpp
b/be/test/vec/function/cast/cast_to_ip_test.cpp
new file mode 100644
index 00000000000..fe4d205fb5b
--- /dev/null
+++ b/be/test/vec/function/cast/cast_to_ip_test.cpp
@@ -0,0 +1,277 @@
+// 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.
+
+#include "cast_test.h"
+#include "vec/data_types/data_type_ipv4.h"
+#include "vec/data_types/data_type_ipv6.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/function/function_test_util.h"
+
+namespace doris::vectorized {
+using namespace ut_type;
+
+IPV4 ipv4_from_string(const std::string& str) {
+ IPV4 ipv4;
+ IPv4Value::from_string(ipv4, str.data(), str.size());
+ return ipv4;
+}
+
+IPV6 ipv6_from_string(const std::string& str) {
+ IPV6 ipv6;
+ IPv6Value::from_string(ipv6, str.data(), str.size());
+ return ipv6;
+}
+
+TEST_F(FunctionCastTest, test_from_string_to_ipv4) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+ DataSet data_set = {
+ // Edge cases
+ {{std::string("null")}, Null()},
+ {{std::string("")}, Null()},
+ {{std::string(" ")}, Null()},
+
+ // Invalid formats
+ {{std::string("x")}, Null()},
+ {{std::string("192.168")}, Null()},
+ {{std::string("192.168.0")}, Null()},
+ {{std::string("192.168.0.256")}, Null()},
+ {{std::string("192.168.0.1.5")}, Null()},
+ {{std::string("192.168.0.a")}, Null()},
+ {{std::string("2001:db8::1")}, Null()}, // IPv6 format
+
+ // Valid formats
+ {{std::string("0.0.0.0")}, ipv4_from_string("0.0.0.0")},
+ {{std::string("127.0.0.1")}, ipv4_from_string("127.0.0.1")},
+ {{std::string("192.168.0.1")}, ipv4_from_string("192.168.0.1")},
+ {{std::string("255.255.255.255")},
ipv4_from_string("255.255.255.255")},
+
+ // With spaces
+ {{std::string(" 10.0.0.1 ")}, ipv4_from_string("10.0.0.1")},
+ {{std::string(" 172.16.0.1 ")}, ipv4_from_string("172.16.0.1")},
+
+ // With leading zeros
+ {{std::string("010.000.000.001")}, ipv4_from_string("10.0.0.1")},
+ {{std::string("001.002.003.004")}, ipv4_from_string("1.2.3.4")},
+ };
+ check_function_for_cast<DataTypeIPv4>(input_types, data_set);
+}
+
+TEST_F(FunctionCastTest, test_from_string_to_ipv6) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+ DataSet data_set = {
+ // Edge cases
+ {{std::string("null")}, Null()},
+ {{std::string("")}, Null()},
+ {{std::string(" ")}, Null()},
+
+ // Invalid formats
+ {{std::string("x")}, Null()},
+ {{std::string("2001:db8::gggg")}, Null()},
+ {{std::string("2001:db8:::1")}, Null()}, // Double ::
+ {{std::string("2001:db8::1::2")}, Null()}, // Multiple ::
+ {{std::string("1:1:::1")}, Null()}, // Double ::
+ {{std::string("1:1:1::1:1:1:1:1")}, Null()}, // :: not use
+ {{std::string("2001:db8:0:0:0:0:0:0:1")}, Null()}, // Too many
segments
+
+ // Valid formats - standard
+ {{std::string("::1")}, ipv6_from_string("::1")}, // Localhost
+ {{std::string("::")}, ipv6_from_string("::")}, // All zeros
+ {{std::string("2001:db8::1")}, ipv6_from_string("2001:db8::1")},
+ {{std::string("2001:db8:0:0:0:0:0:1")},
+ ipv6_from_string("2001:db8:0:0:0:0:0:1")}, // Full form
+ {{std::string("2001:db8::0:1")},
+ ipv6_from_string("2001:db8::0:1")}, // Compressed with non-zero
after ::
+
+ // Mixed IPv6/IPv4
+ {{std::string("::ffff:192.168.0.1")},
+ ipv6_from_string("::ffff:192.168.0.1")}, // IPv4-mapped IPv6
+ {{std::string("::ffff:c0a8:1")},
+ ipv6_from_string("::ffff:c0a8:1")}, // IPv4-mapped IPv6 in hex
+ {{std::string("::192.168.0.1")},
+ ipv6_from_string("::192.168.0.1")}, // IPv4-compatible IPv6
+
+ // With spaces
+ {{std::string(" 2001:db8::1 ")}, ipv6_from_string("2001:db8::1")},
+ {{std::string(" fe80::1 ")}, ipv6_from_string("fe80::1")},
+
+ // Case sensitivity
+ {{std::string("2001:DB8::1")}, ipv6_from_string("2001:db8::1")},
+ {{std::string("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210")},
+ ipv6_from_string("fedc:ba98:7654:3210:fedc:ba98:7654:3210")},
+ };
+ check_function_for_cast<DataTypeIPv6>(input_types, data_set);
+}
+
+TEST_F(FunctionCastTest, test_from_string_to_ipv4_strict_mode) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+
+ // Valid formats in strict mode
+ {
+ DataSet data_set = {
+ {{std::string("0.0.0.0")}, ipv4_from_string("0.0.0.0")},
+ {{std::string("127.0.0.1")}, ipv4_from_string("127.0.0.1")},
+ {{std::string("192.168.0.1")},
ipv4_from_string("192.168.0.1")},
+ {{std::string("255.255.255.255")},
ipv4_from_string("255.255.255.255")},
+ {{std::string(" 10.0.0.1 ")}, ipv4_from_string("10.0.0.1")},
+ {{std::string("010.000.000.001")},
ipv4_from_string("10.0.0.1")},
+ };
+ check_function_for_cast_strict_mode<DataTypeIPv4>(input_types,
data_set);
+ }
+
+ // Invalid formats in strict mode - each should raise error
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv4>(input_types,
+
{{{std::string("x")}, Null()}}, "fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv4>(
+ input_types, {{{std::string("192.168")}, Null()}}, "fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv4>(
+ input_types, {{{std::string("192.168.0.256")}, Null()}},
"fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv4>(input_types,
+ {{{std::string("")},
Null()}}, "fail");
+ }
+}
+
+TEST_F(FunctionCastTest, test_from_string_to_ipv6_strict_mode) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+
+ // Valid formats in strict mode
+ {
+ DataSet data_set = {
+ {{std::string("::1")}, ipv6_from_string("::1")},
+ {{std::string("::")}, ipv6_from_string("::")},
+ {{std::string("2001:db8::1")},
ipv6_from_string("2001:db8::1")},
+ {{std::string("2001:db8:0:0:0:0:0:1")},
ipv6_from_string("2001:db8:0:0:0:0:0:1")},
+ {{std::string("::ffff:192.168.0.1")},
ipv6_from_string("::ffff:192.168.0.1")},
+ {{std::string(" 2001:db8::1 ")},
ipv6_from_string("2001:db8::1")},
+ };
+ check_function_for_cast_strict_mode<DataTypeIPv6>(input_types,
data_set);
+ }
+
+ // Invalid formats in strict mode - each should raise error
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(input_types,
+
{{{std::string("x")}, Null()}}, "fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(
+ input_types, {{{std::string("2001:db8::gggg")}, Null()}},
"fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(
+ input_types, {{{std::string("2001:db8:::1")}, Null()}},
"fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(
+ input_types, {{{std::string("1:1:::1")}, Null()}}, "fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(
+ input_types, {{{std::string(" 1:1:1::1:1:1:1:1")}, Null()}},
"fail");
+ }
+ {
+ check_function_for_cast_strict_mode<DataTypeIPv6>(input_types,
+ {{{std::string("")},
Null()}}, "fail");
+ }
+}
+
+TEST_F(FunctionCastTest, test_ipv4_to_ipv6) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_IPV4};
+ DataSet data_set = {
+ {{ipv4_from_string("0.0.0.0")},
ipv6_from_string("::ffff:0.0.0.0")},
+ {{ipv4_from_string("127.0.0.1")},
ipv6_from_string("::ffff:127.0.0.1")},
+ {{ipv4_from_string("192.168.0.1")},
ipv6_from_string("::ffff:192.168.0.1")},
+ {{ipv4_from_string("255.255.255.255")},
ipv6_from_string("::ffff:255.255.255.255")},
+ };
+ check_function_for_cast<DataTypeIPv6>(input_types, data_set);
+}
+
+TEST_F(FunctionCastTest, test_ip_to_string) {
+ // IPv4 to string
+ {
+ InputTypeSet input_types = {PrimitiveType::TYPE_IPV4};
+ DataSet data_set = {
+ {{ipv4_from_string("0.0.0.0")}, std::string("0.0.0.0")},
+ {{ipv4_from_string("127.0.0.1")}, std::string("127.0.0.1")},
+ {{ipv4_from_string("192.168.0.1")},
std::string("192.168.0.1")},
+ {{ipv4_from_string("255.255.255.255")},
std::string("255.255.255.255")},
+ };
+ check_function_for_cast<DataTypeString>(input_types, data_set);
+ }
+
+ // IPv6 to string
+ {
+ InputTypeSet input_types = {PrimitiveType::TYPE_IPV6};
+ DataSet data_set = {
+ {{ipv6_from_string("::")}, std::string("::")},
+ {{ipv6_from_string("::1")}, std::string("::1")},
+ {{ipv6_from_string("2001:db8::1")},
std::string("2001:db8::1")},
+ {{ipv6_from_string("::ffff:192.168.0.1")},
std::string("::ffff:192.168.0.1")},
+ };
+ check_function_for_cast<DataTypeString>(input_types, data_set);
+ }
+}
+
+TEST_F(FunctionCastTest, test_non_strict_cast_string_to_ipv4) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+ DataSet data_set = {
+ {{std::string("192.168.1.1")}, ipv4_from_string("192.168.1.1")},
+ {{std::string("0.0.0.0")}, ipv4_from_string("0.0.0.0")},
+ {{std::string("255.255.255.255")},
ipv4_from_string("255.255.255.255")},
+ {{std::string("10.20.30.40")}, ipv4_from_string("10.20.30.40")},
+ {{std::string(" 192.168.1.1 ")}, ipv4_from_string("192.168.1.1")},
+ {{std::string("192.168.01.1")}, ipv4_from_string("192.168.1.1")},
+ {{std::string("1.2.3")}, Null()},
+ {{std::string("1.2.3.4.5")}, Null()},
+ {{std::string("256.0.0.1")}, Null()},
+ {{std::string("1.300.2.3")}, Null()},
+ {{std::string("1.2.3.")}, Null()},
+ {{std::string(".1.2.3")}, Null()},
+ {{std::string("1..2.3")}, Null()},
+ {{std::string("a.b.c.d")}, Null()},
+ {{std::string("1.2.+3.4")}, Null()},
+ };
+ check_function_for_cast<DataTypeIPv4>(input_types, data_set);
+}
+
+TEST_F(FunctionCastTest, test_non_strict_cast_string_to_ipv6) {
+ InputTypeSet input_types = {PrimitiveType::TYPE_VARCHAR};
+ DataSet data_set = {
+ {{std::string("2001:db8:85a3:0000:0000:8a2e:0370:7334")},
+ ipv6_from_string("2001:db8:85a3:0000:0000:8a2e:0370:7334")},
+ {{std::string("::")}, ipv6_from_string("::")},
+ {{std::string("2001:db8::")}, ipv6_from_string("2001:db8::")},
+ {{std::string("::ffff:192.168.1.1")},
ipv6_from_string("::ffff:192.168.1.1")},
+ {{std::string(" 2001:db8::1 ")}, ipv6_from_string("2001:db8::1")},
+ {{std::string("2001:db8::1::2")}, Null()},
+ {{std::string("2001:db8:85a3:0000:0000:8a2e:0370:7334:1234")},
Null()},
+ {{std::string("2001:db8:85a3:0000:8a2e:0370")}, Null()},
+ {{std::string("2001:db8:85g3:0000:0000:8a2e:0370:7334")}, Null()},
+ {{std::string("2001:db8::ffff:192.168.1.260")}, Null()},
+ {{std::string("2001:db8::ffff:192.168..1")}, Null()},
+ {{std::string("2001:0db8:85a3:::8a2e:0370:7334")}, Null()},
+ {{std::string("20001:db8::1")}, Null()},
+ };
+ check_function_for_cast<DataTypeIPv6>(input_types, data_set);
+}
+
+} // namespace doris::vectorized
diff --git a/be/test/vec/function/function_test_util.h
b/be/test/vec/function/function_test_util.h
index 4570f1a1db3..c002d4724c5 100644
--- a/be/test/vec/function/function_test_util.h
+++ b/be/test/vec/function/function_test_util.h
@@ -168,10 +168,12 @@ struct ut_input_type<DataTypeHLL> {
template <>
struct ut_input_type<DataTypeIPv4> {
using type = IPV4;
+ inline static type default_value = 0;
};
template <>
struct ut_input_type<DataTypeIPv6> {
using type = IPV6;
+ inline static type default_value = 0;
};
template <>
struct ut_input_type<DataTypeArray> {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java
index 1284ece2ec1..061a620ab2d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Cast.java
@@ -79,7 +79,8 @@ public class Cast extends Expression implements
UnaryExpression, Monotonic {
@Override
public boolean nullable() {
if (ConnectContext.get().getSessionVariable().enableStrictCast()) {
- if (targetType.isNumericType() || targetType.isDateLikeType() ||
targetType.isBooleanType()) {
+ if (targetType.isNumericType() || targetType.isDateLikeType() ||
targetType.isBooleanType()
+ || targetType.isIPType()) {
return child().nullable();
}
DataType childDataType = child().getDataType();
diff --git a/regression-test/data/function_p0/cast/test_cast_to_ip.out
b/regression-test/data/function_p0/cast/test_cast_to_ip.out
new file mode 100644
index 00000000000..9cf8be14724
Binary files /dev/null and
b/regression-test/data/function_p0/cast/test_cast_to_ip.out differ
diff --git a/regression-test/data/nereids_function_p0/fn_test_ip_invalid.csv
b/regression-test/data/nereids_function_p0/fn_test_ip_invalid.csv
index 21344d61bcb..93861abda08 100644
--- a/regression-test/data/nereids_function_p0/fn_test_ip_invalid.csv
+++ b/regression-test/data/nereids_function_p0/fn_test_ip_invalid.csv
@@ -1,5 +1,5 @@
1;256.0.0.1;2001:db8::12345;'256.0.0.1';'2001:db8::12345'
-2;192.168.1.999;2001:db8:::1;'192.168.1.999';'2001:db8:::1'
+2;192.168.1.999;2001:db8::1;'192.168.1.999';'2001:db8::1'
3;300.300.300.300;::fffff:0:0;'300.300.300.300';'::fffff:0:0'
4;192.168.1.1.1;2001:db8::g123;'192.168.1.1.1';'2001:db8::g123'
5;1234.56.78.90;2001:db8::zzz;'1234.56.78.90';'2001:db8::zzz'
@@ -15,16 +15,16 @@
15;192.168.1.;fe80:1234::85a3::7334;'192.168.1.';'fe80:1234::85a3::7334'
16;192.168.1.1;::12345:abcd;'192.168.1.1';'::12345:abcd'
17;10.0.0.1;2001:db8:85a3:0::123::;'10.0.0.1';'2001:db8:85a3:0::123::'
-18;172.16.0.1;2001:db8:::;'172.16.0.1';'2001:db8:::'
+18;172.16.0.1;2001:db8::;'172.16.0.1';'2001:db8::'
19;192.168.1.1;2001:db8:85a3:0000:0000:8a2e:0370:12345;'192.168.1.1';'2001:db8:85a3:0000:0000:8a2e:0370:12345'
20;172.16.0.0;2001:db8:85a3:0:0:0:0:0:0;'172.16.0.0';'2001:db8:85a3:0:0:0:0:0:0'
-21;10.0.0.1;fe80:85a3:::7334;'10.0.0.1';'fe80:85a3:::7334'
+21;10.0.0.1;fe80:85a3::7334;'10.0.0.1';'fe80:85a3::7334'
22;192.168.1.1;2001:db8::85a3::7334;'192.168.1.1';'2001:db8::85a3::7334'
23;172.16.0.1;g123:abcd::85a3::7334;'172.16.0.1';'g123:abcd::85a3::7334'
24;10.0.0.1;2001:db8:85a3:0000:0000:8a2e:0370:abcdg;'10.0.0.1';'2001:db8:85a3:0000:0000:8a2e:0370:abcdg'
25;192.168.0.1;fe80:0000:0000:0000:0000:0000:0000:0001;'192.168.0.1';'fe80:0000:0000:0000:0000:0000:0000:0001'
26;192.168.1.1;12345::abcd;'192.168.1.1';'12345::abcd'
-27;10.0.0.1;::85a3:::7334;'10.0.0.1';'::85a3:::7334'
+27;10.0.0.1;::85a3::7334;'10.0.0.1';'::85a3::7334'
28;172.16.0.0;2001:db8:85a3:0000:0000:8a2e:0370:abcd::;'172.16.0.0';'2001:db8:85a3:0000:0000:8a2e:0370:abcd::'
29;192.168.1.1;2001:db8:85a3:0000::g123;'192.168.1.1';'2001:db8:85a3:0000::g123'
30;10.0.0.1;2001:db8:85a3:0000::0370:abcd:12345;'10.0.0.1';'2001:db8:85a3:0000::0370:abcd:12345'
diff --git a/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
b/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
index 95fff863794..36b8ec754f7 100644
--- a/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
+++ b/regression-test/suites/datatype_p0/ip/test_ip_crud.groovy
@@ -46,7 +46,7 @@ suite("test_ip_crud") {
qt_sql4 "select * from test_unique_ip_crud where ip_v4='119.36.22.147' and
ip_v6='2001:4888:1f:e891:161:26::'"
// Only unique table could be updated
- sql "update test_unique_ip_crud set ip_v4=0, ip_v6='2804:64:0:25::1' where
id=3"
+ sql "update test_unique_ip_crud set ip_v4='0.0.0.0',
ip_v6='2804:64:0:25::1' where id=3"
qt_sql5 "select * from test_unique_ip_crud order by id"
// test ip datatype in aggregate table
diff --git a/regression-test/suites/datatype_p0/ip/test_ip_implicit_cast.groovy
b/regression-test/suites/datatype_p0/ip/test_ip_implicit_cast.groovy
index 30291b3af3a..9e5cb4562ba 100644
--- a/regression-test/suites/datatype_p0/ip/test_ip_implicit_cast.groovy
+++ b/regression-test/suites/datatype_p0/ip/test_ip_implicit_cast.groovy
@@ -35,10 +35,10 @@ suite("test_ip_implicit_cast") {
);
"""
sql "insert into ${tableName} values(-1, NULL, NULL)"
- sql "insert into ${tableName} values(0, 0, '::')"
- sql "insert into ${tableName} values(1, 1, '::1')"
- sql "insert into ${tableName} values(2130706433, 2130706433,
'2001:1b70:a1:610::b102:2')"
- sql "insert into ${tableName} values(4294967295, 4294967295,
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')"
+ sql "insert into ${tableName} values(0, TO_IPV4(IPV4_NUM_TO_STRING(0)),
'::')"
+ sql "insert into ${tableName} values(1, TO_IPV4(IPV4_NUM_TO_STRING(1)),
'::1')"
+ sql "insert into ${tableName}
values(2130706433,TO_IPV4(IPV4_NUM_TO_STRING(2130706433)) ,
'2001:1b70:a1:610::b102:2')"
+ sql "insert into ${tableName}
values(4294967295,TO_IPV4(IPV4_NUM_TO_STRING(4294967295)),
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')"
qt_sql1 "select id, ip_v4, ip_v6 from ${tableName} order by id"
diff --git a/regression-test/suites/function_p0/cast/test_cast_to_ip.groovy
b/regression-test/suites/function_p0/cast/test_cast_to_ip.groovy
new file mode 100644
index 00000000000..8ad3f78e2fb
--- /dev/null
+++ b/regression-test/suites/function_p0/cast/test_cast_to_ip.groovy
@@ -0,0 +1,198 @@
+// 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.
+
+
+suite("test_cast_to_ip") {
+ sql "set debug_skip_fold_constant=true;"
+
+ // Test casting to IPv4 from valid string formats
+ sql "set enable_strict_cast=false;"
+ qt_cast_str_to_ipv4_valid """
+ SELECT
+ CAST('192.168.0.1' AS IPv4) AS ipv4_standard,
+ CAST('127.0.0.1' AS IPv4) AS ipv4_localhost,
+ CAST('0.0.0.0' AS IPv4) AS ipv4_zero,
+ CAST('255.255.255.255' AS IPv4) AS ipv4_broadcast,
+ CAST(' 10.0.0.1 ' AS IPv4) AS ipv4_with_spaces,
+ CAST('010.000.000.001' AS IPv4) AS ipv4_with_leading_zeros;
+ """
+
+ // Test casting to IPv4 from invalid string formats (non-strict mode)
+ qt_cast_str_to_ipv4_invalid """
+ SELECT
+ CAST('not_an_ip' AS IPv4) AS ipv4_invalid_str,
+ CAST('192.168.0' AS IPv4) AS ipv4_incomplete,
+ CAST('192.168.0.256' AS IPv4) AS ipv4_out_of_range,
+ CAST('192.168.0.1.5' AS IPv4) AS ipv4_too_many_parts,
+ CAST('2001:db8::1' AS IPv4) AS ipv4_from_ipv6,
+ CAST('192.168.0' AS IPv4) AS ipv4_too_few_parts,
+ CAST('192.168.0.a' AS IPv4) AS ipv4_non_numeric;
+ """
+
+ qt_cast_str_to_ipv4 """
+ SELECT
+ CAST('192.168.1.1' AS IPv4) AS standard_valid_ipv4,
+ CAST('0.0.0.0' AS IPv4) AS min_boundary_ipv4,
+ CAST('255.255.255.255' AS IPv4) AS max_boundary_ipv4,
+ CAST('10.20.30.40' AS IPv4) AS regular_ipv4,
+ CAST(' 192.168.1.1 ' AS IPv4) AS whitespace_ipv4,
+ CAST('192.168.01.1' AS IPv4) AS leading_zero_ipv4,
+ CAST('1.2.3' AS IPv4) AS missing_segment_ipv4,
+ CAST('1.2.3.4.5' AS IPv4) AS extra_segment_ipv4,
+ CAST('256.0.0.1' AS IPv4) AS first_out_of_range_ipv4,
+ CAST('1.300.2.3' AS IPv4) AS second_out_of_range_ipv4,
+ CAST('1.2.3.' AS IPv4) AS last_segment_missing_ipv4,
+ CAST('.1.2.3' AS IPv4) AS first_segment_missing_ipv4,
+ CAST('1..2.3' AS IPv4) AS empty_segment_ipv4,
+ CAST('a.b.c.d' AS IPv4) AS non_numeric_ipv4,
+ CAST('1.2.+3.4' AS IPv4) AS invalid_symbol_ipv4;
+ """
+
+ qt_cast_str_to_ipv6 """
+ SELECT
+ CAST('2001:db8:85a3:0000:0000:8a2e:0370:7334' AS IPv6) AS
standard_valid_ipv6,
+ CAST('::' AS IPv6) AS zero_ipv6,
+ CAST('2001:db8::' AS IPv6) AS compressed_ipv6,
+ CAST('::ffff:192.168.1.1' AS IPv6) AS ipv4_mapped_ipv6,
+ CAST(' 2001:db8::1 ' AS IPv6) AS whitespace_ipv6,
+ CAST('2001:db8::1::2' AS IPv6) AS double_compression_ipv6,
+ CAST('2001:db8:85a3:0000:0000:8a2e:0370:7334:1234' AS IPv6) AS
too_many_groups_ipv6,
+ CAST('2001:db8:85a3:0000:8a2e:0370' AS IPv6) AS too_few_groups_ipv6,
+ CAST('2001:db8:85g3:0000:0000:8a2e:0370:7334' AS IPv6) AS
invalid_hex_char_ipv6,
+ CAST('2001:db8::ffff:192.168.1.260' AS IPv6) AS
ipv4_part_out_of_range_ipv6,
+ CAST('2001:db8::ffff:192.168..1' AS IPv6) AS ipv4_part_format_error_ipv6,
+ CAST('2001:0db8:85a3:::8a2e:0370:7334' AS IPv6) AS triple_colon_ipv6,
+ CAST('20001:db8::1' AS IPv6) AS first_group_too_long_ipv6;
+ """
+
+
+ // Test casting to IPv6 from valid string formats
+ qt_cast_str_to_ipv6_valid """
+ SELECT
+ CAST('2001:db8::1' AS IPv6) AS ipv6_standard,
+ CAST('::1' AS IPv6) AS ipv6_localhost,
+ CAST('::' AS IPv6) AS ipv6_zero,
+ CAST('2001:db8:0:0:0:0:0:1' AS IPv6) AS ipv6_full,
+ CAST('2001:db8::0:1' AS IPv6) AS ipv6_compressed,
+ CAST(' 2001:db8::1 ' AS IPv6) AS ipv6_with_spaces,
+ CAST('2001:DB8::1' AS IPv6) AS ipv6_uppercase,
+ CAST('2001:db8:85a3:0000:0000:8a2e:0370:7334' AS IPv6) AS
ipv6_full_standard,
+ CAST('2001:db8::' AS IPv6) AS ipv6_compressed_end;
+ """
+
+ // Test IPv6 mapped IPv4 addresses
+ qt_cast_str_to_ipv6_mapped_ipv4 """
+ SELECT
+ CAST('::ffff:192.168.0.1' AS IPv6) AS ipv6_mapped_ipv4,
+ CAST('::ffff:c0a8:1' AS IPv6) AS ipv6_mapped_ipv4_hex,
+ CAST('::192.168.0.1' AS IPv6) AS ipv6_compat_ipv4,
+ CAST('::ffff:192.168.1.1' AS IPv6) AS ipv6_mapped_ipv4_new;
+ """
+
+ // Test casting to IPv6 from invalid string formats (non-strict mode)
+ qt_cast_str_to_ipv6_invalid """
+ SELECT
+ CAST('not_an_ip' AS IPv6) AS ipv6_invalid_str,
+ CAST('2001:db8::gggg' AS IPv6) AS ipv6_invalid_hex,
+ CAST('2001:db8:::1' AS IPv6) AS ipv6_invalid_format,
+ CAST('2001:db8::1::2' AS IPv6) AS ipv6_too_many_compressions,
+ CAST(' 1:1:::1' AS IPv6) AS ipv6_with_double_compression,
+ CAST(' 1:1:1::1:1:1:1:1 ' AS IPv6) AS ipv6_with_not_use_compression,
+ CAST('2001:db8:0:0:0:0:0:0:1' AS IPv6) AS ipv6_too_many_parts;
+ """
+
+ // Test casting between IPv4 and IPv6
+ qt_cast_between_ip_types """
+ SELECT
+ CAST(CAST('192.168.0.1' AS IPv4) AS VARCHAR) AS ipv4_to_string,
+ CAST(CAST('2001:db8::1' AS IPv6) AS VARCHAR) AS ipv6_to_string,
+ CAST(CAST('192.168.0.1' AS IPv4) AS IPv6) AS ipv4_to_ipv6;
+ """
+
+ // Enable strict mode for the same tests
+ sql "set enable_strict_cast=true;"
+
+ // Test casting to IPv4 from valid string formats (strict mode)
+ qt_cast_str_to_ipv4_valid_strict """
+ SELECT
+ CAST('192.168.0.1' AS IPv4) AS ipv4_standard,
+ CAST('127.0.0.1' AS IPv4) AS ipv4_localhost,
+ CAST('0.0.0.0' AS IPv4) AS ipv4_zero,
+ CAST('255.255.255.255' AS IPv4) AS ipv4_broadcast,
+ CAST(' 10.0.0.1 ' AS IPv4) AS ipv4_with_spaces,
+ CAST('010.000.000.001' AS IPv4) AS ipv4_with_leading_zeros;
+ """
+
+ // Test casting to IPv6 from valid string formats (strict mode)
+ qt_cast_str_to_ipv6_valid_strict """
+ SELECT
+ CAST('2001:db8::1' AS IPv6) AS ipv6_standard,
+ CAST('::1' AS IPv6) AS ipv6_localhost,
+ CAST('::' AS IPv6) AS ipv6_zero,
+ CAST('2001:db8:0:0:0:0:0:1' AS IPv6) AS ipv6_full,
+ CAST('2001:db8::0:1' AS IPv6) AS ipv6_compressed,
+ CAST(' 2001:db8::1 ' AS IPv6) AS ipv6_with_spaces,
+ CAST('2001:DB8::1' AS IPv6) AS ipv6_uppercase;
+ """
+
+
+
+ // IPv4 map to IPv6 addresses in strict mode
+ qt_cast_str_to_ipv6_mapped_ipv4_strict """
+ SELECT
+ CAST('192.168.0.0' as IPv4) AS ipv4_address,
+ CAST( CAST('192.168.0.0' as IPv4) as IPv6) AS ipv6_mapped_ipv4,
+ CAST('0.0.0.0' as IPv4) AS ipv4_address2,
+ CAST( CAST('0.0.0.0' as IPv4) as IPv6) AS ipv6_mapped_ipv4_zero;
+ """
+ // Test invalid IP formats in strict mode (should throw error)
+ test {
+ sql "SELECT CAST('not_an_ip' AS IPv4) AS invalid_ipv4;"
+ exception "parse ipv4 fail"
+ }
+
+ test {
+ sql "SELECT CAST('192.168.0.256' AS IPv4) AS out_of_range_ipv4;"
+ exception "parse ipv4 fail"
+ }
+
+ test {
+ sql "SELECT CAST('not_an_ip' AS IPv6) AS invalid_ipv6;"
+ exception "parse ipv6 fail"
+ }
+
+ test {
+ sql "SELECT CAST('2001:db8::gggg' AS IPv6) AS invalid_hex_ipv6;"
+ exception "parse ipv6 fail"
+ }
+
+ test {
+ sql "SELECT CAST('2001:db8:::1' AS IPv6) AS invalid_format_ipv6;"
+ exception "parse ipv6 fail"
+ }
+
+ test {
+ sql "SELECT CAST('1:1:::1' AS IPv6) AS too_many_compressions_ipv6;"
+ exception "parse ipv6 fail"
+ }
+
+ test {
+ sql "SELECT CAST(' 1:1:1::1:1:1:1:1' AS IPv6) AS
too_many_compressions_ipv6;"
+ exception "parse ipv6 fail"
+ }
+
+}
\ No newline at end of file
diff --git a/regression-test/suites/nereids_p0/javaudf/test_javaudf_ip.groovy
b/regression-test/suites/nereids_p0/javaudf/test_javaudf_ip.groovy
index aa079af16d0..b6d739a9e32 100644
--- a/regression-test/suites/nereids_p0/javaudf/test_javaudf_ip.groovy
+++ b/regression-test/suites/nereids_p0/javaudf/test_javaudf_ip.groovy
@@ -66,7 +66,7 @@ suite("nereids_test_javaudf_ip") {
DISTRIBUTED BY HASH(k1) BUCKETS 1
PROPERTIES("replication_num" = "1");
"""
- sql """ insert into test_udf_ip values(1,123,34141,"0.0.0.123") ,
(2,3114,318903,"0.0.0.123") ,
(3,7832131,192837891738927931231,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
+ sql """ insert into test_udf_ip
values(1,'0.0.0.123','::855d',"0.0.0.123") ,
(2,'0.0.12.42','::0.4.221.183',"0.0.0.123") ,
(3,'0.119.130.67','::a:7429:d0d6:6e08:9f5f',"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
qt_select_ipv4_1 """ select k1,k4,java_udf_ipv4_test1(k4) from
test_udf_ip order by k1 """
qt_select_ipv4_2 """ select k1,s,java_udf_ipv4_test2(s) from
test_udf_ip where IS_IPV4_STRING(s) order by k1 """
qt_select_ipv4_3 """ select
java_udf_ipv4_test3(array_sort(array_agg(k4))) from test_udf_ip """
@@ -117,7 +117,7 @@ suite("nereids_test_javaudf_ip") {
DISTRIBUTED BY HASH(k1) BUCKETS 1
PROPERTIES("replication_num" = "1");
"""
- sql """ insert into test_udf_ip values(1,123,34141,"0.0.0.123") ,
(2,3114,318903,"0.0.0.123") ,
(3,7832131,192837891738927931231,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
+ sql """ insert into test_udf_ip
values(1,'0.0.0.123','::855d',"0.0.0.123") ,
(2,'0.0.12.42','::0.4.221.183',"0.0.0.123") ,
(3,'0.119.130.67','::a:7429:d0d6:6e08:9f5f',"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
qt_select_ipv6_1 """ select k1,k6,java_udf_ipv6_test1(k6) from
test_udf_ip order by k1 """
qt_select_ipv6_2 """ select k1,s,java_udf_ipv6_test2(s) from
test_udf_ip where IS_IPV6_STRING(s) order by k1 """
qt_select_ipv6_3 """ select
java_udf_ipv6_test3(array_sort(array_agg(k6))) from test_udf_ip """
diff --git a/regression-test/suites/query_p0/aggregate/array_agg.groovy
b/regression-test/suites/query_p0/aggregate/array_agg.groovy
index c78f84394fd..f58971a0fa9 100644
--- a/regression-test/suites/query_p0/aggregate/array_agg.groovy
+++ b/regression-test/suites/query_p0/aggregate/array_agg.groovy
@@ -317,8 +317,8 @@ suite("array_agg") {
s string
) DISTRIBUTED BY HASH(k1) BUCKETS 1 PROPERTIES("replication_num" =
"1");
"""
- sql """ insert into test_array_agg_ip values(1,123,34141,"0.0.0.123") ,
(2,3114,318903,"0.0.0.123") ,
(3,7832131,192837891738927931231,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
-
+ sql """ insert into test_array_agg_ip
values(1,'0.0.0.123','::855d',"0.0.0.123") ,
(2,'0.0.12.42','::0.4.221.183',"0.0.0.123") ,
(3,'0.119.130.67','::a:7429:d0d6:6e08:9f5f',"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D"),(4,null,null,"2001:0DB8:AC10:FE01:FEED:BABE:CAFE:F00D");
"""
+
qt_select """select array_sort(array_agg(k4)),array_sort(array_agg(k6))
from test_array_agg_ip """
diff --git a/regression-test/suites/statistics/test_analyze_ip_type.groovy
b/regression-test/suites/statistics/test_analyze_ip_type.groovy
index 33a71c438b4..584a05c7204 100644
--- a/regression-test/suites/statistics/test_analyze_ip_type.groovy
+++ b/regression-test/suites/statistics/test_analyze_ip_type.groovy
@@ -36,10 +36,10 @@ suite("test_analyze_ip_type") {
);
"""
sql """insert into ${tableName} values(-1, NULL, NULL)"""
- sql """insert into ${tableName} values(0, 0, '::')"""
- sql """insert into ${tableName} values(1, 1, '::1')"""
- sql """insert into ${tableName} values(2130706433, 2130706433,
'2001:1b70:a1:610::b102:2')"""
- sql """insert into ${tableName} values(4294967295, 4294967295,
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')"""
+ sql """insert into ${tableName} values(0, '0.0.0.0', '::')"""
+ sql """insert into ${tableName} values(1, '0.0.0.1', '::1')"""
+ sql """insert into ${tableName} values(2130706433, '127.0.0.1',
'2001:1b70:a1:610::b102:2')"""
+ sql """insert into ${tableName} values(4294967295, '255.255.255.255',
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')"""
sql """analyze table ${tableName} with sync"""
def result = sql """show column stats ${tableName}"""
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]