Skip to content

Commit

Permalink
MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16…
Browse files Browse the repository at this point in the history
… charset table query

Problem:
When handling a query like this:
  VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin;
Type_handler_string_result::Item_hybrid_func_fix_attributes()
tried to apply character set conversion Item_type_holder,
which causes a crash on DBUG_ASSERT(0) inside Item_type_holder::val_str().

Fix:
Overriding Item_type_holder's methods to avoid this, as follows:

  bool const_item() const { return false; }
  bool is_expensive() { return true; }
  • Loading branch information
abarkov committed May 20, 2020
1 parent 294ac1f commit d4f97e2
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 0 deletions.
25 changes: 25 additions & 0 deletions mysql-test/main/ctype_utf16.result
Original file line number Diff line number Diff line change
Expand Up @@ -2814,3 +2814,28 @@ SET STORAGE_ENGINE=Default;
#
# End of 10.2 tests
#
#
# Start of 10.3 tests
#
#
# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
#
SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf16);
SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t;
1
1
DROP TABLE t1;
VALUES (1) UNION SELECT _utf16 0x0020;
1
1

VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin;


VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin);


#
# End of 10.3 tests
#
21 changes: 21 additions & 0 deletions mysql-test/main/ctype_utf16.test
Original file line number Diff line number Diff line change
Expand Up @@ -934,3 +934,24 @@ let $coll_pad='utf16_bin';
--echo #
--echo # End of 10.2 tests
--echo #

--echo #
--echo # Start of 10.3 tests
--echo #

--echo #
--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
--echo #

SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf16);
SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t;
DROP TABLE t1;
VALUES (1) UNION SELECT _utf16 0x0020;
VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin;
VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin);


--echo #
--echo # End of 10.3 tests
--echo #
12 changes: 12 additions & 0 deletions mysql-test/main/ctype_utf8.result
Original file line number Diff line number Diff line change
Expand Up @@ -11321,5 +11321,17 @@ SELECT x AS 5天内最近一次登录时间 FROM t1;
1
DROP TABLE t1;
#
# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
#
SET NAMES utf8;
VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin;
_latin1 0xDF
ß
a
VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin);
_latin1 0xDF
ß
a
#
# End of 10.3 tests
#
7 changes: 7 additions & 0 deletions mysql-test/main/ctype_utf8.test
Original file line number Diff line number Diff line change
Expand Up @@ -2256,6 +2256,13 @@ INSERT INTO t1 VALUES (1);
SELECT x AS 5天内最近一次登录时间 FROM t1;
DROP TABLE t1;

--echo #
--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
--echo #

SET NAMES utf8;
VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin;
VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin);

--echo #
--echo # End of 10.3 tests
Expand Down
17 changes: 17 additions & 0 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -6602,6 +6602,23 @@ class Item_type_holder: public Item,

enum Type type() const { return TYPE_HOLDER; }
TYPELIB *get_typelib() const { return enum_set_typelib; }
/*
When handling a query like this:
VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin);
Item_type_holder can be passed to
Type_handler_xxx::Item_hybrid_func_fix_attributes()
We don't want the latter to perform character set conversion of a
Item_type_holder by calling its val_str(), which calls DBUG_ASSERT(0).
Let's override const_item() and is_expensive() to avoid this.
Note, Item_hybrid_func_fix_attributes() could probably
have a new argument to distinguish what we need:
- (a) aggregate data type attributes only
- (b) install converters after attribute aggregation
So st_select_lex_unit::join_union_type_attributes() could
ask it to do (a) only, without (b).
*/
bool const_item() const { return false; }
bool is_expensive() { return true; }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
Expand Down

0 comments on commit d4f97e2

Please sign in to comment.