matrixorigin / matrixorigin/matrixone
[Bug]: CRC32(JSON) hashes internal binary encoding instead of JSON text
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
### Problem
`CRC32(JSON)` hashes MatrixOne's internal binary JSON representation instead of the SQL text representation of the JSON value. The returned checksum therefore differs from both `CRC32(CAST(json_value AS CHAR))` in MatrixOne and `CRC32(json_value)` in MySQL.
This is a result-correctness problem: the statement succeeds and returns a plausible unsigned checksum, but that checksum is for different bytes than the SQL value exposed by the JSON expression.
### Reproduction
```sql
CREATE DATABASE crc32_json_repro;
USE crc32_json_repro;
CREATE TABLE t(id INT PRIMARY KEY, js JSON);
INSERT INTO t VALUES
(1, '{"b":2,"a":1}'),
(2, 'null'),
(3, NULL),
(4, '[1,true,"x"]'),
(5, '1');
SELECT id,
CAST(js AS CHAR) AS json_text,
CRC32(js) AS direct_crc,
CRC32(CAST(js AS CHAR)) AS text_crc
FROM t ORDER BY id;
```
### MatrixOne result
```text
id JSON text CRC32(js) CRC32(CAST(js AS CHAR))
1 {"a": 1, "b": 2} 581034396 733321759
2 null 1387456365 634125391
3 SQL NULL NULL NULL
4 [1, true, "x"] 3799633758 3071756745
5 1 2248188523 2212294583
```
### Expected result / MySQL 8.0.45 result
The direct JSON expression and explicit character conversion identify the same SQL JSON value and return the same checksum:
```text
id CRC32(js) CRC32(CAST(js AS CHAR))
1 733321759 733321759
2 634125391 634125391
3 NULL NULL
4 3071756745 3071756745
5 2212294583 2212294583
```
### Scope and controls
- Object, array, numeric scalar, JSON null, and SQL NULL were covered.
- Ordinary text, VARBINARY including `0x00`/`0xff`, BIGINT, DECIMAL, DATETIME, invalid SHA2 lengths, and prepared reuse were also compared; their checksum/hash values match MySQL.
- The JSON mismatch reproduced in three fresh database runs.
- Explicit `CAST(js AS CHAR)` is a working control and returns the MySQL checksum.
### Code location
`crc32TypeMatch` intentionally preserves every varlen input without a cast. JSON is varlen internally, so it reaches `builtInCrc32`, which hashes the vector bytes directly. Those bytes are MatrixOne's binary JSON encoding rather than the JSON text representation used for SQL string conversion.
### Environment
- MatrixOne: official `main` commit `0c3a04f390adaf6281fd592a49778ea5b1155e67`
- MySQL control: 8.0.45
- Local single-node MatrixOne deployment
Contributor guide
Assessment
This issue has not been assessed yet.