Skip to content

Commit

Permalink
MDEV-20795 CAST(inet6 AS BINARY) returns wrong result
Browse files Browse the repository at this point in the history
  • Loading branch information
abarkov committed Oct 11, 2019
1 parent d04f2de commit b5fae7f
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 14 deletions.
105 changes: 105 additions & 0 deletions plugin/type_inet/mysql-test/type_inet/type_inet6.result
Expand Up @@ -720,6 +720,99 @@ t1 CREATE TABLE `t1` (
`a` varchar(39) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('ffff::ffff');
CREATE TABLE t2 AS SELECT
CAST(a AS CHAR),
CAST(a AS CHAR(39)),
CAST(a AS CHAR(530)),
CAST(a AS CHAR(65535)),
CAST(a AS CHAR(66000)),
CAST(a AS CHAR(16777215)),
CAST(a AS CHAR(16777216))
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`CAST(a AS CHAR)` varchar(39) DEFAULT NULL,
`CAST(a AS CHAR(39))` varchar(39) DEFAULT NULL,
`CAST(a AS CHAR(530))` text DEFAULT NULL,
`CAST(a AS CHAR(65535))` text DEFAULT NULL,
`CAST(a AS CHAR(66000))` mediumtext DEFAULT NULL,
`CAST(a AS CHAR(16777215))` mediumtext DEFAULT NULL,
`CAST(a AS CHAR(16777216))` longtext DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
CAST(a AS CHAR) ffff::ffff
CAST(a AS CHAR(39)) ffff::ffff
CAST(a AS CHAR(530)) ffff::ffff
CAST(a AS CHAR(65535)) ffff::ffff
CAST(a AS CHAR(66000)) ffff::ffff
CAST(a AS CHAR(16777215)) ffff::ffff
CAST(a AS CHAR(16777216)) ffff::ffff
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('ffff::ffff');
CREATE TABLE t2 AS SELECT
CAST(a AS BINARY(4)) AS cb4,
CAST(a AS BINARY) AS cb,
CAST(a AS BINARY(16)) AS cb16,
CAST(a AS BINARY(32)) AS cb32,
CAST(a AS BINARY(530)) AS cb530,
CAST(a AS BINARY(65535)) AS cb65535,
CAST(a AS BINARY(66000)) AS cb66000,
CAST(a AS BINARY(16777215)) AS cb16777215,
CAST(a AS BINARY(16777216)) AS cb16777216
FROM t1 LIMIT 0;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`cb4` binary(4) DEFAULT NULL,
`cb` binary(16) DEFAULT NULL,
`cb16` binary(16) DEFAULT NULL,
`cb32` binary(32) DEFAULT NULL,
`cb530` varbinary(530) DEFAULT NULL,
`cb65535` blob DEFAULT NULL,
`cb66000` mediumblob DEFAULT NULL,
`cb16777215` mediumblob DEFAULT NULL,
`cb16777216` longblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE TABLE t2 AS SELECT
CAST(a AS BINARY(4)) AS cb4,
CAST(a AS BINARY) AS cb,
CAST(a AS BINARY(16)) AS cb16,
CAST(a AS BINARY(32)) AS cb32,
CAST(a AS BINARY(530)) AS cb530,
CAST(a AS BINARY(65535)) AS cb65535
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`cb4` binary(4) DEFAULT NULL,
`cb` binary(16) DEFAULT NULL,
`cb16` binary(16) DEFAULT NULL,
`cb32` binary(32) DEFAULT NULL,
`cb530` varbinary(530) DEFAULT NULL,
`cb65535` blob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
HEX(cb4),
HEX(cb),
HEX(cb16),
HEX(cb32),
LENGTH(cb530),
LENGTH(cb65535)
FROM t2;
HEX(cb4) FFFF0000
HEX(cb) FFFF000000000000000000000000FFFF
HEX(cb16) FFFF000000000000000000000000FFFF
HEX(cb32) FFFF000000000000000000000000FFFF00000000000000000000000000000000
LENGTH(cb530) 530
LENGTH(cb65535) 65535
DROP TABLE t2;
DROP TABLE t1;
#
# Implicit conversion to other types in INSERT
#
Expand Down Expand Up @@ -1516,3 +1609,15 @@ SELECT HEX(a) FROM t1;
HEX(a)
20010DB8000000000000FF0000428329
DROP TABLE t1;
#
# MDEV-20795 CAST(inet6 AS BINARY) returns wrong result
#
CREATE OR REPLACE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
SELECT HEX(CAST(a AS BINARY)) FROM t1;
HEX(CAST(a AS BINARY))
20010DB8000000000000FF0000428329
SELECT HEX(CAST(a AS BINARY(16))) FROM t1;
HEX(CAST(a AS BINARY(16)))
20010DB8000000000000FF0000428329
DROP TABLE t1;
65 changes: 65 additions & 0 deletions plugin/type_inet/mysql-test/type_inet/type_inet6.test
Expand Up @@ -383,6 +383,61 @@ CREATE TABLE t1 AS SELECT CAST(CAST('::' AS INET6) AS CHAR) AS a;
SHOW CREATE TABLE t1;
DROP TABLE t1;

CREATE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('ffff::ffff');
CREATE TABLE t2 AS SELECT
CAST(a AS CHAR),
CAST(a AS CHAR(39)),
CAST(a AS CHAR(530)),
CAST(a AS CHAR(65535)),
CAST(a AS CHAR(66000)),
CAST(a AS CHAR(16777215)),
CAST(a AS CHAR(16777216))
FROM t1;
SHOW CREATE TABLE t2;
--vertical_results
SELECT * FROM t2;
--horizontal_results
DROP TABLE t2;
DROP TABLE t1;

CREATE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('ffff::ffff');
CREATE TABLE t2 AS SELECT
CAST(a AS BINARY(4)) AS cb4,
CAST(a AS BINARY) AS cb,
CAST(a AS BINARY(16)) AS cb16,
CAST(a AS BINARY(32)) AS cb32,
CAST(a AS BINARY(530)) AS cb530,
CAST(a AS BINARY(65535)) AS cb65535,
CAST(a AS BINARY(66000)) AS cb66000,
CAST(a AS BINARY(16777215)) AS cb16777215,
CAST(a AS BINARY(16777216)) AS cb16777216
FROM t1 LIMIT 0;
SHOW CREATE TABLE t2;
DROP TABLE t2;

CREATE TABLE t2 AS SELECT
CAST(a AS BINARY(4)) AS cb4,
CAST(a AS BINARY) AS cb,
CAST(a AS BINARY(16)) AS cb16,
CAST(a AS BINARY(32)) AS cb32,
CAST(a AS BINARY(530)) AS cb530,
CAST(a AS BINARY(65535)) AS cb65535
FROM t1;
SHOW CREATE TABLE t2;
--vertical_results
SELECT
HEX(cb4),
HEX(cb),
HEX(cb16),
HEX(cb32),
LENGTH(cb530),
LENGTH(cb65535)
FROM t2;
--horizontal_results
DROP TABLE t2;
DROP TABLE t1;

--echo #
--echo # Implicit conversion to other types in INSERT
Expand Down Expand Up @@ -1049,3 +1104,13 @@ INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
ALTER TABLE t1 MODIFY a BINARY(16);
SELECT HEX(a) FROM t1;
DROP TABLE t1;

--echo #
--echo # MDEV-20795 CAST(inet6 AS BINARY) returns wrong result
--echo #

CREATE OR REPLACE TABLE t1 (a INET6);
INSERT INTO t1 VALUES ('2001:db8::ff00:42:8329');
SELECT HEX(CAST(a AS BINARY)) FROM t1;
SELECT HEX(CAST(a AS BINARY(16))) FROM t1;
DROP TABLE t1;
48 changes: 48 additions & 0 deletions plugin/type_inet/sql_type_inet.cc
Expand Up @@ -1216,6 +1216,54 @@ class in_inet6 :public in_vector
};


class Item_char_typecast_func_handler_inet6_to_binary:
public Item_handled_func::Handler_str
{
public:
const Type_handler *return_type_handler() const override
{
return &type_handler_string;
}
const Type_handler *
type_handler_for_create_select(const Item_handled_func *item) const
{
if (item->max_length > MAX_FIELD_VARCHARLENGTH)
return Type_handler::blob_type_handler(item->max_length);
if (item->max_length > 255)
return &type_handler_varchar;
return &type_handler_string;
}
bool fix_length_and_dec(Item_handled_func *xitem) const override
{
return false;
}
String *val_str(Item_handled_func *item, String *to) const override
{
DBUG_ASSERT(dynamic_cast<const Item_char_typecast*>(item));
return static_cast<Item_char_typecast*>(item)->
val_str_binary_from_native(to);
}
};


static const Item_char_typecast_func_handler_inet6_to_binary
item_char_typecast_func_handler_inet6_to_binary;


bool Type_handler_inet6::
Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const
{
if (item->cast_charset() == &my_charset_bin)
{
item->fix_length_and_dec_native_to_binary(Inet6::binary_length());
item->set_func_handler(&item_char_typecast_func_handler_inet6_to_binary);
return false;
}
item->fix_length_and_dec_str();
return false;
}


bool
Type_handler_inet6::character_or_binary_string_to_native(THD *thd,
const String *str,
Expand Down
6 changes: 1 addition & 5 deletions plugin/type_inet/sql_type_inet.h
Expand Up @@ -930,11 +930,7 @@ class Type_handler_inet6: public Type_handler
}
bool
Item_char_typecast_fix_length_and_dec(Item_char_typecast *item)
const override
{
item->fix_length_and_dec_str();
return false;
}
const override;
bool
Item_time_typecast_fix_length_and_dec(Item_time_typecast *item) const override
{
Expand Down
50 changes: 50 additions & 0 deletions sql/item_func.h
Expand Up @@ -467,9 +467,46 @@ class Item_handled_func: public Item_func
virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0;
virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0;
virtual const Type_handler *return_type_handler() const= 0;
virtual const Type_handler *
type_handler_for_create_select(const Item_handled_func *item) const
{
return return_type_handler();
}
virtual bool fix_length_and_dec(Item_handled_func *) const= 0;
};

class Handler_str: public Handler
{
public:
String *val_str_ascii(Item_handled_func *item, String *str) const
{
return item->Item::val_str_ascii(str);
}
double val_real(Item_handled_func *item) const
{
DBUG_ASSERT(item->is_fixed());
StringBuffer<64> tmp;
String *res= item->val_str(&tmp);
return res ? item->double_from_string_with_check(res) : 0.0;
}
longlong val_int(Item_handled_func *item) const
{
DBUG_ASSERT(item->is_fixed());
StringBuffer<22> tmp;
String *res= item->val_str(&tmp);
return res ? item->longlong_from_string_with_check(res) : 0;
}
my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const
{
return item->val_decimal_from_string(to);
}
bool get_date(THD *thd, Item_handled_func *item, MYSQL_TIME *to,
date_mode_t fuzzydate) const
{
return item->get_date_from_string(thd, to, fuzzydate);
}
};

/**
Abstract class for functions returning TIME, DATE, DATETIME or string values,
whose data type depends on parameters and is set at fix_fields time.
Expand All @@ -496,6 +533,11 @@ class Item_handled_func: public Item_func
{
return &type_handler_string;
}
const Type_handler *
type_handler_for_create_select(const Item_handled_func *item) const
{
return return_type_handler()->type_handler_for_tmp_table(item);
}
double val_real(Item_handled_func *item) const
{
return Temporal_hybrid(item).to_double();
Expand Down Expand Up @@ -613,6 +655,14 @@ class Item_handled_func: public Item_func
{
return m_func_handler->return_type_handler();
}
Field *create_field_for_create_select(MEM_ROOT *root, TABLE *table)
{
DBUG_ASSERT(fixed);
const Type_handler *h= m_func_handler->type_handler_for_create_select(this);
return h->make_and_init_table_field(root, &name,
Record_addr(maybe_null),
*this, table);
}
String *val_str(String *to)
{
return m_func_handler->val_str(this, to);
Expand Down

0 comments on commit b5fae7f

Please sign in to comment.