Commit b1d1dc90 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-31626 implement inet4->inet6 cast

parent 63da557e
......@@ -246,7 +246,8 @@ longlong Item_func_is_ipv6::val_int()
{
DBUG_ASSERT(fixed());
String_ptr_and_buffer<STRING_BUFFER_USUAL_SIZE> tmp(args[0]);
return !tmp.is_null() && !Type_handler_inet6::Fbt_null(*tmp.string()).is_null();
return !tmp.is_null() && tmp.string()->strstr(STRING_WITH_LEN(":")) >= 0 &&
!Type_handler_inet6::Fbt_null(*tmp.string()).is_null();
}
/**
......
#
# Start of 10.10 tests
#
#
# MDEV-23287 The INET4 data type
#
CREATE TABLE t1 (i4 INET4, i6 INET6);
SELECT * FROM t1 WHERE i4=i6;
ERROR HY000: Illegal parameter data types inet4 and inet6 for operation '='
SELECT COALESCE(i4,i6) FROM t1 WHERE i4=i6;
ERROR HY000: Illegal parameter data types inet4 and inet6 for operation 'coalesce'
SELECT LEAST(i4,i6) FROM t1 WHERE i4=i6;
ERROR HY000: Illegal parameter data types inet4 and inet6 for operation 'least'
SELECT i4 FROM t1 UNION ALL SELECT i6 FROM t1;
ERROR HY000: Illegal parameter data types inet4 and inet6 for operation 'UNION'
DROP TABLE t1;
create table t1 (i4 inet4 not null);
create table t2 (i6 inet6 not null);
insert t1 values ('127.0.0.1'), ('192.168.1.2'), ('1.2.3.4'), ('8.8.8.8');
insert t2 values ('2001:db8::ff00:42:8329'), ('fe80::42:70ff:fe94:6b97');
select * from t1;
i4
127.0.0.1
192.168.1.2
1.2.3.4
8.8.8.8
select * from t2;
i6
2001:db8::ff00:42:8329
fe80::42:70ff:fe94:6b97
select * from t1 union select * from t2;
i4
::ffff:127.0.0.1
::ffff:192.168.1.2
::ffff:1.2.3.4
::ffff:8.8.8.8
2001:db8::ff00:42:8329
fe80::42:70ff:fe94:6b97
insert t2 select * from t1;
select * from t2;
i6
2001:db8::ff00:42:8329
fe80::42:70ff:fe94:6b97
::ffff:127.0.0.1
::ffff:192.168.1.2
::ffff:1.2.3.4
::ffff:8.8.8.8
select * from t1, t2 where t1.i4=t2.i6;
i4 i6
127.0.0.1 ::ffff:127.0.0.1
192.168.1.2 ::ffff:192.168.1.2
1.2.3.4 ::ffff:1.2.3.4
8.8.8.8 ::ffff:8.8.8.8
select coalesce(i4,i6) from t1, t2 where i4=i6;
coalesce(i4,i6)
::ffff:127.0.0.1
::ffff:192.168.1.2
::ffff:1.2.3.4
::ffff:8.8.8.8
select least(i4,i6) from t1, t2 where i4=i6;
least(i4,i6)
::ffff:127.0.0.1
::ffff:192.168.1.2
::ffff:1.2.3.4
::ffff:8.8.8.8
alter table t1 modify i4 inet6;
select * from t1;
i4
::ffff:127.0.0.1
::ffff:192.168.1.2
::ffff:1.2.3.4
::ffff:8.8.8.8
drop table t1, t2;
#
# End of 10.10 tests
# End of 11.2 tests
#
--echo #
--echo # Start of 10.10 tests
--echo #
--echo #
--echo # MDEV-23287 The INET4 data type
--echo #
# Mixing INET6 and INET4 is not implemented yet
create table t1 (i4 inet4 not null);
create table t2 (i6 inet6 not null);
insert t1 values ('127.0.0.1'), ('192.168.1.2'), ('1.2.3.4'), ('8.8.8.8');
insert t2 values ('2001:db8::ff00:42:8329'), ('fe80::42:70ff:fe94:6b97');
select * from t1;
select * from t2;
select * from t1 union select * from t2;
insert t2 select * from t1;
select * from t2;
select * from t1, t2 where t1.i4=t2.i6;
CREATE TABLE t1 (i4 INET4, i6 INET6);
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT * FROM t1 WHERE i4=i6;
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT COALESCE(i4,i6) FROM t1 WHERE i4=i6;
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT LEAST(i4,i6) FROM t1 WHERE i4=i6;
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT i4 FROM t1 UNION ALL SELECT i6 FROM t1;
select coalesce(i4,i6) from t1, t2 where i4=i6;
select least(i4,i6) from t1, t2 where i4=i6;
DROP TABLE t1;
alter table t1 modify i4 inet6;
select * from t1;
drop table t1, t2;
--echo #
--echo # End of 10.10 tests
--echo # End of 11.2 tests
--echo #
......@@ -269,6 +269,12 @@ bool Inet6::ascii_to_fbt(const char *str, size_t str_length)
return true;
}
if (group_start_ptr == str)
{
dst[10]= dst[11]= (unsigned char) 0xff;
dst+= 12;
}
tmp.to_record(dst, IN_ADDR_SIZE);
dst += IN_ADDR_SIZE;
chars_in_group= 0;
......@@ -519,3 +525,35 @@ const Name &Inet4::default_value()
static Name def(STRING_WITH_LEN("0.0.0.0"));
return def;
}
static const Type_handler *inet4()
{ return Type_handler_inet4::singleton(); }
static const Type_handler *inet6()
{ return Type_handler_inet6::singleton(); }
const Type_handler *Type_collection_inet::find_in_array(const Type_handler *a,
const Type_handler *b,
int start) const
{
if (a == b) return a;
if (a != inet6() && b->type_collection() == this) // inet6 or inet4
std::swap(a, b);
/*
Search in the array for an element, equal to `b`.
If found - return `a`, if not found - return NULL.
Array is terminated by `a`.
Start the search from `start`
*/
static const Type_handler *arr[]={ &type_handler_varchar,
&type_handler_string, &type_handler_tiny_blob, &type_handler_blob,
&type_handler_medium_blob, &type_handler_hex_hybrid,
// in aggregate_for_comparison() all types above cannot happen
&type_handler_null, &type_handler_long_blob, inet4(), inet6() };
for (int i= start; arr[i] != a; i++)
if (arr[i] == b)
return a;
return NULL;
}
......@@ -42,9 +42,38 @@ class Inet6: public FixedBinTypeStorage<IN6_ADDR_SIZE, IN6_ADDR_MAX_CHAR_LENGTH>
static const Name &default_value();
};
class Type_collection_inet: public Type_collection
{
const Type_handler *find_in_array(const Type_handler *what,
const Type_handler *stop, int start) const;
public:
const Type_handler *aggregate_for_result(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, 0); }
const Type_handler *aggregate_for_min_max(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, 0); }
const Type_handler *aggregate_for_comparison(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, 6); } // skip types that cannot happen here
const Type_handler *aggregate_for_num_op(const Type_handler *a,
const Type_handler *b)
const override
{ return NULL; }
static Type_collection_inet *singleton()
{
static Type_collection_inet tc;
return &tc;
}
};
#include "sql_type_fixedbin.h"
typedef Type_handler_fbt<Inet6> Type_handler_inet6;
typedef Type_handler_fbt<Inet6, Type_collection_inet> Type_handler_inet6;
/***********************************************************************/
......@@ -57,7 +86,7 @@ class Inet4: public FixedBinTypeStorage<IN_ADDR_SIZE, IN_ADDR_MAX_CHAR_LENGTH>
static const Name &default_value();
};
typedef Type_handler_fbt<Inet4> Type_handler_inet4;
typedef Type_handler_fbt<Inet4, Type_collection_inet> Type_handler_inet4;
#endif /* SQL_TYPE_INET_H */
......@@ -63,7 +63,7 @@ static struct st_mariadb_data_type plugin_descriptor_type_uuid=
const Type_handler *Type_collection_uuid::find_in_array(const Type_handler *a,
const Type_handler *b,
bool for_cmp) const
int start) const
{
if (a == b) return a;
......@@ -83,6 +83,7 @@ const Type_handler *Type_collection_uuid::find_in_array(const Type_handler *a,
Search in the array for an element, equal to `b`.
If found - return `a`, if not found - return NULL.
Array is terminated by `a`.
Start the search from `start`
*/
static const Type_handler *arr[]={ &type_handler_varchar,
&type_handler_string, &type_handler_tiny_blob, &type_handler_blob,
......@@ -92,7 +93,7 @@ const Type_handler *Type_collection_uuid::find_in_array(const Type_handler *a,
&type_handler_null, &type_handler_long_blob,
Type_handler_uuid_old::singleton(), Type_handler_uuid_new::singleton() };
for (int i= for_cmp ? 6 : 0; arr[i] != a; i++)
for (int i= start; arr[i] != a; i++)
if (arr[i] == b)
return a;
return NULL;
......
......@@ -283,20 +283,20 @@ class Type_collection_uuid: public Type_collection
{
const Type_handler *find_in_array(const Type_handler *what,
const Type_handler *stop,
bool for_comparison) const;
int start) const;
public:
const Type_handler *aggregate_for_result(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, false); }
{ return find_in_array(a, b, 0); }
const Type_handler *aggregate_for_min_max(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, false); }
{ return find_in_array(a, b, 0); }
const Type_handler *aggregate_for_comparison(const Type_handler *a,
const Type_handler *b)
const override
{ return find_in_array(a, b, true); }
{ return find_in_array(a, b, 6); } // skip types that cannot happen here
const Type_handler *aggregate_for_num_op(const Type_handler *a,
const Type_handler *b)
const override
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment