Bug #111195 There is a logical error in source code
Submitted: 30 May 2023 7:34 Modified: 30 May 2023 8:11
Reporter: Xiong Wang Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[30 May 2023 7:34] Xiong Wang
Description:
The following debug information show a possible logical error. I marked key information prefix with ==> inlined.

The following logical error might cause a TRUNCATE warning, but it's useless. Because MySQL doesn't check such a warning returned value during UNION operation, so such a warning is not reported. However, if such a function is called by other plan which might check the returned value, it will cause some problem.

Thread 43 "mysqld" hit Breakpoint 6, well_formed_copy_nchars (to_cs=0x7c3ff00 <my_charset_utf8mb4_0900_ai_ci>, to=0x7fff38b8b7b2 "", to_length=88, 
    from_cs=0x7af6e80 <my_charset_latin1>, from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, from_length=23, nchars=22, well_formed_error_pos=0x7fffe9aa2eb0, 
    cannot_convert_error_pos=0x7fffe9aa2ea8, from_end_pos=0x7fffe9aa2ea0) at /home/simon/work/inlist/Parallel_Query/sql-common/sql_string.cc:829
829          (to_cs == from_cs) || my_charset_same(from_cs, to_cs)) {
(gdb) fin
Run till exit from #0  well_formed_copy_nchars (to_cs=0x7c3ff00 <my_charset_utf8mb4_0900_ai_ci>, to=0x7fff38b8b7b2 "", to_length=88, from_cs=0x7af6e80 <my_charset_latin1>, 
    from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, from_length=23, nchars=22, well_formed_error_pos=0x7fffe9aa2eb0, cannot_convert_error_pos=0x7fffe9aa2ea8, 
    from_end_pos=0x7fffe9aa2ea0) at /home/simon/work/inlist/Parallel_Query/sql-common/sql_string.cc:829
0x00000000035b944d in field_well_formed_copy_nchars (to_cs=0x7c3ff00 <my_charset_utf8mb4_0900_ai_ci>, to=0x7fff38b8b7b2 "9999999.", '9' <repeats 14 times>, to_length=88, 
    from_cs=0x7af6e80 <my_charset_latin1>, from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, from_length=23, nchars=22, well_formed_error_pos=0x7fffe9aa2eb0, 
    cannot_convert_error_pos=0x7fffe9aa2ea8, from_end_pos=0x7fffe9aa2ea0) at /home/simon/work/inlist/Parallel_Query/sql/field.cc:1480
1480      size_t res = well_formed_copy_nchars(
Value returned is $155 = 22
(gdb) fin
Run till exit from #0  0x00000000035b944d in field_well_formed_copy_nchars (to_cs=0x7c3ff00 <my_charset_utf8mb4_0900_ai_ci>, to=0x7fff38b8b7b2 "9999999.", '9' <repeats 14 times>, 
    to_length=88, from_cs=0x7af6e80 <my_charset_latin1>, from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, from_length=23, nchars=22, well_formed_error_pos=0x7fffe9aa2eb0, 
    cannot_convert_error_pos=0x7fffe9aa2ea8, from_end_pos=0x7fffe9aa2ea0) at /home/simon/work/inlist/Parallel_Query/sql/field.cc:1480
0x00000000035cb444 in Field_varstring::store (this=0x7fff38afe1c0, from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, length=23, cs=0x7af6e80 <my_charset_latin1>)
    at /home/simon/work/inlist/Parallel_Query/sql/field.cc:6562
6562      copy_length = field_well_formed_copy_nchars(
Value returned is $156 = 22
(gdb) n
6567      if (length_bytes == 1)
(gdb) 
6568        *ptr = (uchar)copy_length;
(gdb) 
6572      return check_string_copy_error(well_formed_error_pos,
(gdb) s
Field_longstr::check_string_copy_error (this=0x7fff38afe1c0, well_formed_error_pos=0x0, cannot_convert_error_pos=0x0, from_end_pos=0x7fffe9aa2f13 "9", end=0x7fffe9aa2f14 "", 
    count_spaces=true, cs=0x7af6e80 <my_charset_latin1>) at /home/simon/work/inlist/Parallel_Query/sql/field.cc:6033
6033      THD *thd = table->in_use;
(gdb) n
6035      if (!(pos = well_formed_error_pos) && !(pos = cannot_convert_error_pos))
(gdb) 
6036        return report_if_important_data(from_end_pos, end, count_spaces);
(gdb) s
Field_longstr::report_if_important_data (this=0x7fff38afe1c0, pstr=0x7fffe9aa2f13 "9", end=0x7fffe9aa2f14 "", count_spaces=true)
    at /home/simon/work/inlist/Parallel_Query/sql/field.cc:6072
6072      if (pstr < end)  // String is truncated
(gdb) n
6074        if (test_if_important_data(field_charset, pstr, end)) {
(gdb) p pstr<end ==》By here, optimizer will release a TRUNCATE warning.
$157 = true
(gdb)  f 1
#1  0x00000000035c95a3 in Field_longstr::check_string_copy_error (this=0x7fff38afe1c0, well_formed_error_pos=0x0, cannot_convert_error_pos=0x0, from_end_pos=0x7fffe9aa2f13 "9", 
    end=0x7fffe9aa2f14 "", count_spaces=true, cs=0x7af6e80 <my_charset_latin1>) at /home/simon/work/inlist/Parallel_Query/sql/field.cc:6036
6036        return report_if_important_data(from_end_pos, end, count_spaces);
(gdb) f 2
#2  0x00000000035cb4b8 in Field_varstring::store (this=0x7fff38afe1c0, from=0x7fffe9aa2efd "9999999.", '9' <repeats 15 times>, length=23, cs=0x7af6e80 <my_charset_latin1>)
    at /home/simon/work/inlist/Parallel_Query/sql/field.cc:6572
6572      return check_string_copy_error(well_formed_error_pos,
(gdb) l
6567      if (length_bytes == 1)
6568        *ptr = (uchar)copy_length;
6569      else
6570        int2store(ptr, static_cast<uint16>(copy_length));
6571    
6572      return check_string_copy_error(well_formed_error_pos,
6573                                     cannot_convert_error_pos, from_end_pos,
6574                                     from + length, true, cs);
6575    }
6576    
(gdb) p from_end_pos-from + 1
$158 = 23 ==>Here we can see whole decimal values can be converted into varchar.(Note:length of '9999999.999999999999999'string is 23). 
(gdb) p from + length ==>But here the expression of 'from + length' is same as 'from + 23'. In other words, the value of from_end_pos must be less than the one of 'from + 23. Here it's an obvious mistake.
$159 = 0x7fffe9aa2f14 ""
(gdb) p from_end_pos
$160 = 0x7fffe9aa2f13 "9"
(gdb) p length
$161 = 23

How to repeat:
select 9999999.999999999999999 union select -3.40282e1 union select '1';
[30 May 2023 8:11] MySQL Verification Team
Hello Xiong Wang,

Thank you for the report and feedback.

regards,
Umesh