Prepared plan cache causes incorrect NULL-safe comparison for nullable TIME columns
Author: idle-labCreated Aug 26, 2026Updated Sep 17, 2026
Labelstype/bugcontributionsig/plannerseverity/criticalmay-affects-7.5may-affects-8.1affects-8.5affects-26.3
Bug Report
Please answer these questions before submitting your issue. Thanks!
1. Minimal reproduce step (Required)
DROP TABLE IF EXISTS t;
CREATE TABLE t (
tm TIME NULL
);
INSERT INTO t VALUES (NULL), ('12:00:00');
PREPARE stmt FROM
'SELECT COUNT(*) FROM t WHERE tm <=> ?';
-- Build the prepared plan with a valid value.
SET @p = '12:00:00';
EXECUTE stmt USING @p;
-- Reuse the cached plan with an invalid temporal value.
SET @p = 'not-a-time';
EXECUTE stmt USING @p;For comparison, repeat the same test with:
SET SESSION tidb_enable_prepared_plan_cache = OFF;2. What did you expect to see? (Required)
Both plan-cache-enabled and plan-cache-disabled executions should return 0.
not-a-time is an invalid non-NULL value. It should not be treated as SQL NULL in a NULL-safe comparison.
3. What did you see instead (Required)
With the prepared plan cache enabled:
mysql> SET SESSION tidb_enable_prepared_plan_cache = ON;
Query OK, 0 rows affected (0.001 sec)
mysql> SET @p = '12:00:00';
Query OK, 0 rows affected (0.000 sec)
mysql> EXECUTE s USING @p;
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set (0.001 sec)
mysql> SET @p = 'not-a-time';
Query OK, 0 rows affected (0.000 sec)
mysql> EXECUTE s USING @p;
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set, 2 warnings (0.006 sec)With the prepared plan cache disabled:
mysql> SET SESSION tidb_enable_prepared_plan_cache = OFF;
Query OK, 0 rows affected (0.001 sec)
mysql> SET @p = '12:00:00';
Query OK, 0 rows affected (0.001 sec)
mysql> EXECUTE s USING @p;
+----------+
| COUNT(*) |
+----------+
| 1 |
+----------+
1 row in set (0.005 sec)
mysql> SET @p = 'not-a-time';
Query OK, 0 rows affected (0.000 sec)
mysql> EXECUTE s USING @p;
+----------+
| COUNT(*) |
+----------+
| 0 |
+----------+
1 row in set, 1 warning (0.002 sec)4. What is your TiDB version? (Required)
mysql> select tidb_version();
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v7.1.9-0.2-16-gd41b737498-dirty
Edition: Enterprise
Core Version: v8.5.5
Git Commit Hash: d41b737498814ac64b350a0b920ad1d94bc2fc32
Git Branch: fix/time-column-temporal-comparison-7.1.9-0
UTC Build Time: 2026-08-26 09:15:56
GoVersion: go1.25.10
Race Enabled: false
Check Table Before Drop: false
Store: tikv |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.002 sec)Source: pingcap/tidb