matrixorigin / matrixorigin/matrixone
[Bug]: prepared SET inserts reject label strings as uint64
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Description
Prepared INSERTs into a MySQL `SET` column reject normal label strings such as
`a` or `a,b` by trying to convert them to an unsigned integer. Numeric SET
indexes still work. Literal SQL, Connector/J client-prepared statements, and
MySQL server-prepared statements accept the same label values.
The failure affects both MySQL binary-protocol prepared statements and SQL
`PREPARE` / `EXECUTE`.
## Environment
- Branch: `main`
- Commit: `47e022e10f2dbdf5f6b440417f8be80908027e63`
- Deployment: local `mo-service`, 1 Log / 1 TN / 1 CN
- Connector/J: 8.0.33 and 8.0.15
- JDBC server path: `useServerPrepStmts=true`, `cachePrepStmts=false`,
`emulateUnsupportedPstmts=false`
- Control: MySQL 8.0.46
## Steps to reproduce
```sql
create database prepared_set_repro;
use prepared_set_repro;
create table t(id int primary key, tags set('a','b','c'));
```
JDBC binary prepared statement:
```java
try (PreparedStatement ps = connection.prepareStatement(
"insert into t(id,tags) values (?,?)")) {
ps.setInt(1, 1);
ps.setString(2, "a,b");
ps.executeUpdate();
}
```
SQL prepared statement:
```sql
prepare p from 'insert into t(id,tags) values (?,?)';
set @id = 2, @tags = 'a,b';
execute p using @id, @tags;
```
## Actual behavior
Both prepared paths fail without inserting a row:
```text
SQLState HY000 / error 20203
invalid argument cast to uint64, bad value a,b
```
`setString("a")` fails in the same way. Binding integer `3`, or the numeric
string `"3"`, succeeds and stores `a,b`.
## Expected behavior
Prepared INSERT should apply normal MySQL SET assignment semantics and store
label strings such as `a` and `a,b`. MySQL 8.0 accepts both values through the
same binary and SQL prepared paths.
## Stability and controls
- MatrixOne binary server-prepared reproduction: 3/3 with Connector/J 8.0.33.
- MatrixOne SQL `PREPARE` reproduction: 3/3.
- Connector/J 8.0.15: same MatrixOne failure in 3/3 runs.
- MatrixOne `useServerPrepStmts=false`: label INSERT succeeds in 3/3 runs.
- MatrixOne literal `INSERT ... 'a,b'`: succeeds.
- MySQL 8.0.46 server/client prepared and SQL prepared controls: all succeed in
3/3 runs.
- Failed executions leave no partial row; the connection remains usable.
- ENUM label INSERT is a passing control.
## Code analysis
MatrixOne represents a SET column with a `uint64` storage type plus its member
definition. The special assignment conversion is selected in
`pkg/sql/plan/make.go` (`funcCastForSetType`) from the prepare-time expression
type. In this path the late-bound string reaches numeric index conversion,
which is consistent with the exact `cast to uint64` error and with integer
bindings succeeding. The fix should preserve label conversion for string
bindings while retaining numeric-index semantics.
## Regression coverage
Add real binary-protocol and SQL prepared regressions for single and multiple
SET labels, numeric indexes, NULL, invalid labels, repeated rebinding, batch
INSERT, and recovery after a rejected value. Keep literal/client-prepared and
MySQL-compatible stored-value controls.
## Related
- #26873 concerns ENUM/YEAR covering-index extraction, not SET assignment.
- #27328 concerns input parameter metadata, not SET value conversion.
Contributor guide
Assessment
This issue has not been assessed yet.