pingcap / pingcap/tidb

planner: plan cache may return wrong temporal results when fractional seconds precision changes

Open
#69,449 0 comments 0 reactions 0 assignees View on GitHub
severity/moderate sig/planner type/bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.