Bug #116726 Issues with the combination of CAST and DATE.
Submitted: 20 Nov 2024 8:22 Modified: 20 Nov 2024 8:49
Reporter: PeiQi Luo Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S1 (Critical)
Version:8.4.2, 8.0.40 OS:Any
Assigned to: CPU Architecture:Any

[20 Nov 2024 8:22] PeiQi Luo
Description:
These two queries are equivalent because they implement the same filtering logic, albeit with different syntax.
In the original query, the COALESCE function evaluates the first condition (lineitem.l_returnflag) <= (lineitem.l_commitdate). If this condition is not NULL, it is used for filtering. Otherwise, the second condition ( 'p' ) in (lineitem.l_receiptdate, lineitem.l_linestatus) is evaluated.
In the rewritten query, a CASE WHEN statement explicitly handles the logic of COALESCE. If (l_returnflag <= l_commitdate) is not NULL, it uses this condition for filtering. Otherwise, it evaluates whether cast('p' as date) equals l_receiptdate or 'p' equals l_linestatus.
Both queries ultimately evaluate the same filtering criteria: prioritize the first condition if it is not NULL, and fallback to the second condition otherwise. 
Further analysis reveals that in the query, the string 'p' is compared with two columns. In the rewritten SQL, explicit type conversion is used, causing 'p' to be explicitly cast to a date type. Although the original query performs an implicit type conversion to convert 'p' to a date type, the explicit type conversion in the rewritten SQL leads to the error.

How to repeat:
This link provides the exported sql file for the database:
https://github.com/LLuopeiqi/newtpcd/blob/main/mysql/tpcd.sql

--original
select all lineitem.l_commitdate as ref0 from lineitem 
where coalesce((lineitem.l_returnflag) <= (lineitem.l_commitdate),
               ( 'p' ) in (lineitem.l_receiptdate, lineitem.l_linestatus));
return 6005 rows

--rewritten
SELECT l_commitdate AS ref0 FROM lineitem 
WHERE CASE WHEN l_returnflag <= l_commitdate IS NOT NULL 
	THEN l_returnflag <= l_commitdate 
    ELSE cast('p' as date) = l_receiptdate OR 'p' = l_linestatus END;
return 5905 rows
[20 Nov 2024 8:49] MySQL Verification Team
Hello PQ L,

Thank you for the report and feedback.

regards,
Umesh