matrixorigin / matrixorigin/matrixone

[Compatibility]: ADDTIME and SUBTIME attach the current date to TIME-like strings

Open
#28,500 0 comments 0 reactions 1 assignee Claimed by @jiangxinmeng1 View on GitHub
area/compatibility kind/bug needs-triage
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.