matrixorigin / matrixorigin/matrixone
[Compatibility]: DATE_ADD, DATE_SUB, and TIMESTAMPADD preserve TIMESTAMP type instead of DATETIME
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## 现象
`DATE_ADD()`、`DATE_SUB()` 和 `TIMESTAMPADD()` 的输入是 `TIMESTAMP` 列时,MatrixOne 将结果继续解析为 `TIMESTAMP`;MySQL 8.0.46 将这类日期时间算术结果解析为 `DATETIME`。该差异会进入 view/CTAS 元数据,并改变物化结果在会话时区切换后的值。
下面使用 `TIMESTAMP(0)` 隔离类型问题;`DATE_ADD/DATE_SUB` 的小数秒精度问题已由 #28122 单独跟踪。
```sql
CREATE DATABASE interval_ts_repro;
USE interval_ts_repro;
SET time_zone = '+00:00';
CREATE TABLE src(id INT PRIMARY KEY, ts TIMESTAMP(0), dt DATETIME(0));
INSERT INTO src VALUES
(1, '2024-01-01 01:02:03', '2024-01-01 01:02:03');
CREATE VIEW v AS
SELECT
DATE_ADD(ts, INTERVAL 1 SECOND) AS da_ts,
DATE_SUB(ts, INTERVAL 1 DAY) AS ds_ts,
TIMESTAMPADD(SECOND, 1, ts) AS ta_ts,
DATE_ADD(dt, INTERVAL 1 SECOND) AS da_dt
FROM src;
SELECT column_name, data_type, datetime_precision
FROM information_schema.columns
WHERE table_schema = 'interval_ts_repro' AND table_name = 'v'
ORDER BY ordinal_position;
```
MatrixOne view 元数据:
```text
da_ts timestamp 0
ds_ts timestamp 0
ta_ts timestamp 0
da_dt datetime 0
```
MySQL 8.0.46:
```text
da_ts datetime 0
ds_ts datetime 0
ta_ts datetime 0
da_dt datetime 0
```
`DATE_ADD/DATE_SUB` 还可直接物化出不同语义:
```sql
CREATE TABLE copied AS
SELECT
DATE_ADD(ts, INTERVAL 1 SECOND) AS da_ts,
DATE_SUB(ts, INTERVAL 1 DAY) AS ds_ts,
DATE_ADD(dt, INTERVAL 1 SECOND) AS da_dt
FROM src;
SET time_zone = '+08:00';
SELECT CAST(da_ts AS CHAR), CAST(ds_ts AS CHAR), CAST(da_dt AS CHAR)
FROM copied;
```
MatrixOne 将两个 `TIMESTAMP` 派生列从创建时的 `01:02:04` / `01:02:03` 转换为 `09:02:04` / `09:02:03`;`DATETIME` 控制列不变。MySQL 的三个 CTAS 列均为 `DATETIME`,切换时区后都保持创建时的墙钟值。
`TIMESTAMPADD()` 的 CTAS 当前另受 #28562 阻塞,但 view 元数据已经能独立确认其返回类型差异。
## 影响
- view/CTAS schema inference 与 MySQL 不一致;
- MatrixOne 将日期时间算术的物化结果保存为绝对时间,跨会话时区读取时发生转换;
- MySQL 将结果保存为 `DATETIME` 墙钟值,不随读取会话时区改变。
## 代码定位
`pkg/sql/plan/function/list_builtIn.go` 中以下 overload 将 `TIMESTAMP` 输入的返回类型声明为 `T_timestamp`:
- `DATE_ADD` overload 4;
- `DATE_SUB` overload 4;
- `TIMESTAMPADD` overload 2/6。
对应执行路径也返回 `types.Timestamp`。相邻的 `DATETIME` 输入返回 `DATETIME`,符合 MySQL。
## 验证范围
- MatrixOne: latest `main` `ac660ae56ecd37bab3dd8c61193617a323377029`
- MySQL oracle: 8.0.46
- DATE_ADD / DATE_SUB / TIMESTAMPADD
- TIMESTAMP 与 DATETIME 控制
- view 和 CTAS 元数据、`+00:00` 创建后在 `+08:00` 读取
- 3 个全新数据库重复,结果一致
MySQL 文档明确说明 `DATE_ADD/DATE_SUB` 的首参数为 `DATETIME` 或 `TIMESTAMP` 时返回 `DATETIME`:
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add
Contributor guide
Assessment
This issue has not been assessed yet.