Bug #112397 | Inconsistent results caused by JOIN tables and CHAR function | ||
---|---|---|---|
Submitted: | 20 Sep 2023 14:55 | Modified: | 25 Jul 2024 22:57 |
Reporter: | Zuming Jiang | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
Version: | 8.0 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[20 Sep 2023 14:55]
Zuming Jiang
[21 Sep 2023 8:43]
MySQL Verification Team
Hi Mr. Jiang, Thank you for your bug report. However , this is not a bug. There are rules on the simplifications of the queries or transformation of the same into the ones that are expected to return the same result. There are many logical errors in your queries, but one is crucial. Using CHAR() conversion on the non-existent value returns no results what so ever. Any expression involving non-value as considered as an empty result. Empty result is not "" , nor NULL nor anything similar. According to the SQL standard, this leads to the undefined behaviour. Not a bug.
[21 Sep 2023 10:34]
Zuming Jiang
Thank you for checking this issue! I thought MySQL would set the "empty result" as NULL in default (I selected ref_8.vkey from the join table, and it was NULL), so I did not realize that it is an undefined behavior. Now I know it. Thank you for your feedback and I will then refine the tool accordingly. Best wishes, Zuming
[21 Sep 2023 11:46]
MySQL Verification Team
Mr Jiang, You are truly welcome.
[18 Dec 2023 10:52]
MySQL Verification Team
Hi Mr. Jiang, This is just to inform you that we discovered that there is a problem with CHAR function, after all. It is a bit different, then what you reported, but we are verifying your report, since it will also solve this problem as well. Verified as reported. Since only versions 8.0 and higher are maintained, we are verifying this bug for 8.0 and higher versions.
[18 Dec 2023 11:33]
Zuming Jiang
Thanking you for verifying it!
[25 Jul 2024 22:57]
Jon Stephens
Documented fix as follows in the MySQL 9.0.0 changelog: A different result was obtained when a column reference argument to the CHAR() function was replaced with a CASE() expression that was essentially the same as the column reference. This took place when the CHAR() function was placed in the WHERE clause of an outer join, and the column reference was from the inner table of the outer join. An example of such a query is shown here: SELECT 1 AS c_0 FROM t0 LEFT JOIN t1 ON t0.vkey = t1.vkey WHERE CHAR(CASE WHEN FALSE THEN t1.vkey ELSE t1.vkey END) NOT LIKE 'X'; A wrong value was obtained when the column reference was used directly; the CHAR() function in the WHERE clause was used to convert the outer join to an inner join, although this is correct only when NULL as the argument implies a NULL result, which is not true of CHAR(). The implementation detail that enforces this conversion is that the function's not_null_tables() property function returns the map bit of the table, but when the column reference was replaced with the CASE expression, the CASE did not propagate the not_null_tables() value and keep the outer join from being optimized improperly to an inner join. We fix this problem by setting the CHAR() function's null_on_null property to false instead of true, which ensures that not_null_tables() returns 0 rather than the table's map bit, so that that the outer join is not converted to an inner join. Closed.
[26 Jul 2024 9:49]
MySQL Verification Team
Thank you, Jon.