matrixorigin / matrixorigin/matrixone
[Compatibility]: ADDTIME and SUBTIME attach the current date to TIME-like strings
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Problem
`ADDTIME()` and `SUBTIME()` attach the current UTC date to a TIME-like string first argument in MatrixOne. MySQL keeps TIME-like string arithmetic in the time domain.
The MatrixOne value therefore changes with the calendar date on which the query runs, changes the result type to `DATETIME(6)`, and converts legitimate negative or greater-than-24-hour time results into dates around today.
Tested on MatrixOne `main` commit `f0c31cd4b830be32442cf329e0a3fb08aa9c16c3` and MySQL 8.3.0. Each MatrixOne reproduction was repeated three times.
## Minimal reproduction
```sql
SELECT ADDTIME('12:00:00','01:00:00');
SELECT SUBTIME('00:00:00','00:00:00.000001');
SELECT ADDTIME('23:59:59.999999','00:00:00.000002');
SELECT ADDTIME('12:00:00','1 01:02:03.000004');
```
MatrixOne on 2026-09-09 returns:
```text
2026-09-09 13:00:00.000000
2026-09-08 23:59:59.999999
2026-09-10 00:00:00.000001
2026-09-10 13:02:03.000004
```
MySQL returns:
```text
13:00:00
-00:00:00.000001
24:00:00.000001
37:02:03.000004
```
## Row, prepared, and persistence coverage
The same behavior occurs when both inputs are `VARCHAR` columns and when they are bound through SQL `PREPARE`/`EXECUTE`.
For a view over `VARCHAR` inputs:
- MatrixOne exposes both ADDTIME and SUBTIME columns as `DATETIME(6)`;
- MySQL exposes them as `VARCHAR(29)` and preserves whether each row represents a time or datetime string.
CTAS persists MatrixOne's calendar-dependent values into DATETIME columns. MySQL persists the corresponding time strings into VARCHAR columns.
MatrixOne also accepts a datetime-shaped second string such as `'2024-01-01 01:00:00'` as if it were a one-hour TIME operand, while MySQL returns `NULL` for that invalid second operand.
## Controls
- `ADDTIME(CAST('12:00:00' AS TIME(6)), '01:00:00')` returns TIME `13:00:00` in both systems.
- Datetime-like string first arguments such as `'2024-01-02 12:00:00'` produce the same datetime value in both systems.
- NULL propagation agrees.
- Invalid first strings produce NULL in both systems (MatrixOne currently omits MySQL's warning, but that is not the main issue here).
- MatrixOne remains healthy after the full vector and persistence matrix.
## Code analysis
`pkg/sql/plan/function/list_builtIn.go` registers every string/string ADDTIME and SUBTIME overload with a fixed `DATETIME(6)` return type.
`addTimeToString` and `subTimeFromString` in `pkg/sql/plan/function/func_binary.go` first try `types.ParseDatetime`; when a TIME string is found instead, they call `time1.ToDatetime(scale)`. `types.Time.ToDatetime` in `pkg/container/types/time.go` explicitly uses `Today(time.UTC)` as its date component.
This discards the original TIME-vs-DATETIME domain and makes a deterministic time calculation depend on the execution date.
## Expected behavior
TIME-like string first arguments should remain in the time domain, including negative and greater-than-24-hour results. Datetime-like first arguments should remain datetime-like. The result metadata and CTAS/view persistence should preserve that distinction without introducing today's date.
Contributor guide
Assessment
This issue has not been assessed yet.