diff options
author | Alexander Barkov <bar@mariadb.com> | 2020-05-20 11:53:09 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2020-05-20 11:53:09 +0400 |
commit | d4f97e2086848cedfdd35a6c1cf286f8dad26c5c (patch) | |
tree | 0395f96dd3a403f94285ccab1515913802211f7a /sql/item.h | |
parent | 294ac1fbab306e97dad3588a00e3527f2056e7e4 (diff) | |
download | mariadb-git-d4f97e2086848cedfdd35a6c1cf286f8dad26c5c.tar.gz |
MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 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; }
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/sql/item.h b/sql/item.h index 39451d2631a..769e6b80ca9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -6602,6 +6602,23 @@ public: 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 *); |