matrixorigin / matrixorigin/matrixone
[Compatibility]: UUID() native result type breaks MySQL string expression semantics
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
### MatrixOne version
Latest `main` at `f72ca9efbeb3a7c673701e4a135cc6670c33cfde` (`VERSION()` reports `8.0.30-MatrixOne-v1.3.0`).
MySQL control: 8.3.0.
### What is different
MySQL returns `UUID()` as a 36-character string. MatrixOne exposes `UUID()` as its native `UUID` SQL type. The native result does not participate in several ordinary string-expression contexts with MySQL semantics.
This is separate from the UUID version difference in #28380: changing the generated UUID from v7 to v1 would not change these result-type and coercion behaviors.
### Reproduction and observed behavior
#### String predicates and scalar functions
```sql
SELECT UUID() IN ('fallback');
SELECT GREATEST(UUID(), 'fallback');
SELECT LEAST(UUID(), 'fallback');
```
MatrixOne returns:
```text
invalid UUID length: 8
invalid argument function greatest, bad value [UUID VARCHAR]
invalid argument function least, bad value [UUID VARCHAR]
```
MySQL 8.3 treats `UUID()` as a string: the `IN` expression returns `0`, and `GREATEST`/`LEAST` return the lexicographically selected string.
#### Set operation
```sql
SELECT 'fallback'
UNION ALL
SELECT UUID();
```
MatrixOne returns the UUID row truncated to the width of the first literal:
```text
fallback
01a07f76
```
MySQL returns the complete 36-character UUID. Reversing the MatrixOne branches (`SELECT UUID() UNION ALL SELECT 'fallback'`) also returns the full UUID, so the result depends on branch order.
#### CTAS metadata
```sql
CREATE TABLE ctas AS SELECT UUID() AS u;
SHOW CREATE TABLE ctas;
```
MatrixOne derives `u UUID NOT NULL`; MySQL derives `u VARCHAR(36)`. This makes the return-type difference externally visible in persisted schema as well as scalar evaluation.
All behaviors above were reproduced in three independent runs on each engine.
### Controls
Explicit conversion isolates the problem to UUID/string type resolution:
```sql
SELECT CAST(UUID() AS CHAR) IN ('fallback');
SELECT GREATEST(CAST(UUID() AS CHAR), 'fallback');
```
Both execute in MatrixOne with the same result shape as MySQL (`0` and `'fallback'`). `CASE`, `IF`, `COALESCE`, string length, concatenation, and the reverse-order `UUID() UNION ALL SELECT 'fallback'` also execute, so UUID generation and its textual formatting are not the cause.
### Compatibility contract and implementation
- [MySQL's UUID reference](https://dev.mysql.com/doc/refman/8.4/en/miscellaneous-functions.html) specifies a 128-bit UUID represented as a `utf8mb3` string in the 36-character canonical format.
- [MatrixOne's current UUID documentation](https://github.com/matrixorigin/matrixorigin.io/blob/main/docs/MatrixOne/Reference/Functions-and-Operators/Other/uuid.md) declares full MySQL compatibility and repeats the string-return contract.
- MatrixOne's function registry instead declares the return type as [`types.T_uuid`](https://github.com/matrixorigin/matrixone/blob/f72ca9efbeb3a7c673701e4a135cc6670c33cfde/pkg/sql/plan/function/list_builtIn.go#L14954-L14968).
### Expected behavior
The MySQL-compatible `UUID()` function result should be usable as a 36-character string in comparison, scalar, set-operation, and CTAS contexts without explicit casts, and set-operation branch order must not truncate a generated UUID. MatrixOne-specific versioned generators or explicit casts to the native `UUID` type can retain native-type behavior separately.
Contributor guide
Assessment
This issue has not been assessed yet.