planner: plan cache may return wrong temporal results when fractional seconds precision changes
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
Please answer these questions before submitting your issue. Thanks!
### 1. Minimal reproduce step (Required)
Plan cache parameter type compatibility ignored the fractional seconds precision (FSP) of fractionable temporal parameters. As a result, cached plans could be reused across values such as DATETIME(0) and DATETIME(6). Any cacheable expression whose compiled result metadata or evaluation depends on that FSP may return rounded or truncated temporal values.
```sql
set time_zone = '+00:00';
drop table if exists t;
create table t (
a int primary key,
d0 datetime(0)
);
insert into t values (1, null);
-- Baseline: normal non-prepared execution keeps the datetime(6) fraction.
select ifnull(d0, cast('2024-01-01 12:34:56.789012' as datetime(6))) as v from t where a = 1;
prepare st from 'select ifnull(d0, ?) as v from t where a = 1';
set @p = cast('2024-01-01 12:34:56' as datetime(0));
execute st using @p;
execute st using @p;
select @@last_plan_from_cache;
set @p = cast('2024-01-01 12:34:56.789012' as datetime(6));
execute st using @p;
select @@last_plan_from_cache;
```
### 2. What did you expect to see? (Required)
The non-prepared baseline returns:
2024-01-01 12:34:56.789012
After switching the prepared parameter from datetime(0) to datetime(6), TiDB should not reuse the cached plan compiled for datetime(0):
2024-01-01 12:34:56.789012
And the `last_plan_from_cache` should be zero.
### 3. What did you see instead (Required)
```
mysql> select ifnull(d0, cast('2024-01-01 12:34:56.789012' as datetime(6))) as v
-> from t where a = 1;
+----------------------------+
| v |
+----------------------------+
| 2024-01-01 12:34:56.789012 |
+----------------------------+
1 row in set (0.00 sec)
mysql>
mysql> prepare st from 'select ifnull(d0, ?) as v from t where a = 1';
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> set @p = cast('2024-01-01 12:34:56' as datetime(0));
Query OK, 0 rows affected (0.00 sec)
mysql> execute st using @p;
+---------------------+
| v |
+---------------------+
| 2024-01-01 12:34:56 |
+---------------------+
1 row in set (0.00 sec)
mysql> execute st using @p;
+---------------------+
| v |
+---------------------+
| 2024-01-01 12:34:56 |
+---------------------+
1 row in set (0.00 sec)
mysql> select @@last_plan_from_cache;
+------------------------+
| @@last_plan_from_cache |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.00 sec)
mysql>
mysql> set @p = cast('2024-01-01 12:34:56.789012' as datetime(6));
Query OK, 0 rows affected (0.00 sec)
mysql> execute st using @p;
+---------------------+
| v |
+---------------------+
| 2024-01-01 12:34:57 |
+---------------------+
1 row in set (0.00 sec)
mysql> select @@last_plan_from_cache;
+------------------------+
| @@last_plan_from_cache |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.00 sec)
```
### 4. What is your TiDB version? (Required)
latest master
Contributor guide
Research direction
Start with the SQL reproducer and trace plan-cache parameter type compatibility for fractionable temporal values, focusing on how fractional seconds precision is compared. Done means switching a prepared parameter from DATETIME(0) to DATETIME(6) does not reuse the cached plan, preserves 2024-01-01 12:34:56.789012, and reports last_plan_from_cache as zero.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100