• Alexander Barkov's avatar
    Bug#11753363 (bug#44793) CHARACTER SETS: CASE CLAUSE, UCS2 OR UTF32, FAILURE · 14263b22
    Alexander Barkov authored
    Problem: in case of string CASE/WHEN arguments with different
    character sets, Item_func_case::find_item() called comparator
    cmp_items[x] on mixed character set Items, so a 8-bit value could
    be errouneously referenced to as being utf16/utf32 value,
    which led to crash on DBUG_ASSERT() because of wrong value length.
    This was wrong, as string comparator expects arguments in the same
    character set.
    
    Fix: modify Item_func_case's argument list after calling
    agg_arg_charsets_for_comparison() - put the Items in "agg" array
    back to "args", because some of the Items in the "agg" array might
    have been changed to character set converters:
    - to Item_func_conv_charset for non-constant items
    - to Item_string for constant items
    
    In other words, perform the same substitution which is done in
    all other operations string comparison or string result operations:
    
    Replace
      CASE         latin1_item              WHEN utf16_item THEN ... END
    to
      CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END
    
    Replace
      CASE utf16_item WHEN         latin1_item              THEN ... END
    to
      CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END
    
    
      @ mysql-test/r/ctype_utf16.result
      @ mysql-test/r/ctype_utf32.result
      @ mysql-test/t/ctype_utf16.test
      @ mysql-test/t/ctype_utf32.test
      Adding tests
    
      @ sql/item_cmpfunc.cc
      Put "agg" back to "args".
    
      @ sql/sql_string.cc
      Backporting a fix for String::set_or_copy_aligned() from 5.6,
      for better test coverage:
      "SELECT _utf16 0x61" should expand the string to 0x0061 rather
      than to 0x000061.
      This fix was made in 5.6 under terms of "WL#4616 Implement UTF16-LE".
    14263b22
sql_string.cc 31.1 KB