Bug #118658 Issue with NULL Detection for DATE-Type Columns in Derived Tables After Derived Merge
Submitted: 15 Jul 6:11 Modified: 15 Jul 6:14
Reporter: Xingyu Yang (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Data Types Severity:S3 (Non-critical)
Version:9.2.0, 8.0, 8.0.42 OS:Any
Assigned to: CPU Architecture:Any

[15 Jul 6:11] Xingyu Yang
Description:
When a `DATE`-type column from a derived table (e.g., `ttt.b` in `COALESCE(ttt.b, t.a)`) is merged via derived merge optimization, the nullability check may fail due to `Item_view_ref` lacking an overridden `get_date()` method. This causes the execution to fall back to `item_ref::get_date()`, which incorrectly evaluates nullability for `DATE` types, unlike other data types (e.g., strings, integers) that have proper overrides.

How to repeat:
DROP TABLE  IF EXISTS t;
CREATE TABLE t(id INT PRIMARY KEY ,a DATE);
INSERT INTO t (id,a)VALUES (1,'2025-01-01'),(2,'2025-01-02');

SELECT ttt.b,t.a,COALESCE(NULL,t.a),COALESCE(ttt.b,t.a),COALESCE(ttt.b,t.id)
FROM t
LEFT JOIN 
    (SELECT STR_TO_DATE('2024-01-03','%Y-%m-%d') AS b
     FROM  (SELECT 1)tt
     WHERE 1=0 )ttt ON 1=1;

# result
+------+------------+--------------------+---------------------+----------------------+
| b    | a          | COALESCE(NULL,t.a) | COALESCE(ttt.b,t.a) | COALESCE(ttt.b,t.id) |
+------+------------+--------------------+---------------------+----------------------+
| NULL | 2025-01-01 | 2025-01-01         | 2024-01-03          | 1                    |
| NULL | 2025-01-02 | 2025-01-02         | 2024-01-03          | 2                    |
+------+------------+--------------------+---------------------+----------------------+
# COALESCE(ttt.b, t.a) should be equal to COALESCE(NULL, t.a) because ttt.b is null.

set optimizer_switch="derived_merge=off";
SELECT ttt.b,t.a,COALESCE(NULL,t.a),COALESCE(ttt.b,t.a),COALESCE(ttt.b,t.id)
FROM t
LEFT JOIN 
    (SELECT STR_TO_DATE('2024-01-03','%Y-%m-%d') AS b
     FROM  (SELECT 1)tt
     WHERE 1=0 )ttt ON 1=1;

# Correct result
+------+------------+--------------------+---------------------+----------------------+
| b    | a          | COALESCE(NULL,t.a) | COALESCE(ttt.b,t.a) | COALESCE(ttt.b,t.id) |
+------+------------+--------------------+---------------------+----------------------+
| NULL | 2025-01-01 | 2025-01-01         | 2025-01-01          | 1                    |
| NULL | 2025-01-02 | 2025-01-02         | 2025-01-02          | 2                    |
+------+------------+--------------------+---------------------+----------------------+

Suggested fix:
Implement `Item_view_ref::get_date()` to properly handle null detection for `DATE` types.

diff --git a/sql/item.cc b/sql/item.cc
index 9c19fcc344d..9b750d7a468 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -8892,6 +8892,14 @@ bool Item_view_ref::val_json(Json_wrapper *wr) {
   return super::val_json(wr);
 }
 
+bool Item_view_ref::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) {
+  if (has_null_row()) {
+    null_value = true;
+    return true;
+  }
+  return super::get_date(ltime, fuzzydate);
+}
+
 bool Item_view_ref::is_null() {
   if (has_null_row()) return true;
 
diff --git a/sql/item.h b/sql/item.h
index 2d276107258..7d6cb31fcdc 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -6243,6 +6243,7 @@ class Item_view_ref final : public Item_ref {
   String *val_str(String *str) override;
   bool val_bool() override;
   bool val_json(Json_wrapper *wr) override;
+  bool get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) override;
   bool is_null() override;
   bool send(Protocol *prot, String *tmp) override;
   bool collect_item_field_or_view_ref_processor(uchar *arg) override;
[15 Jul 6:12] Xingyu Yang
bugfix based on mysql-9.2.0

(*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: 0001-bugfix.patch (application/octet-stream, text), 1.25 KiB.

[15 Jul 6:14] MySQL Verification Team
Hello Xingyu Yang,

Thank you for the report and feedback.

regards,
Umesh