matrixorigin / matrixorigin/matrixone

[Compatibility]: UUID() native result type breaks MySQL string expression semantics

Open
#28,382 0 comments 0 reactions 1 assignee Claimed by @XuPeng-SH 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

### 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

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.