matrixorigin / matrixorigin/matrixone
[Bug]: server-prepared ParameterMetaData reports NULL for all parameters
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Description
For a MySQL binary-protocol server prepared statement, MatrixOne reports every
parameter through JDBC `ParameterMetaData` as `Types.NULL` / `NULL`, even when
the marker is bound to a typed table column or an explicit cast. Execution and
stored data are correct; the protocol metadata is not.
## Environment
- Branch: `main`
- Commit: `47e022e10f2dbdf5f6b440417f8be80908027e63`
- Deployment: local `mo-service`, 1 Log / 1 TN / 1 CN, MySQL protocol on
`127.0.0.1:26001`
- Control: MySQL 8.0.46 on `127.0.0.1:26002`
- Connector/J: 8.0.33 and 8.0.15, with
`useServerPrepStmts=true`, `cachePrepStmts=false`, and
`emulateUnsupportedPstmts=false`
## Steps to reproduce
1. Create a table with `INT`, `DECIMAL`, `VARCHAR`, and `BLOB` columns.
2. Prepare these statements through JDBC and inspect each parameter with
`PreparedStatement.getParameterMetaData()` before execution:
```sql
SELECT i FROM t WHERE id = ? AND s = ?;
INSERT INTO t(id, i, d, s, b) VALUES (?, ?, ?, ?, ?);
UPDATE t SET i = ?, d = ?, s = ?, b = ? WHERE id = ?;
```
3. Execute the statements with integer, decimal, string, and binary values and
read the rows back.
## Actual behavior
On MatrixOne, every parameter in every shape is reported as:
```text
type=0, name=NULL, class=java.lang.Object, precision=0, scale=0
```
This includes the `id` lookup, decimal assignment, string assignment, and blob
assignment. The same statements execute and persist the expected rows, so the
failure is isolated to the prepare response metadata.
## Expected behavior
The prepare response should provide a meaningful, non-NULL parameter type for
markers whose type can be inferred from a column or cast. MySQL returns typed
metadata for the same JDBC calls (for example BIGINT, DECIMAL, VARCHAR, and
LONGBLOB); a direct `SELECT ?` is reported as VARCHAR by Connector/J.
## Stability and controls
- MatrixOne reproducer: 3/3 with Connector/J 8.0.33.
- MySQL control: 3/3 returns non-NULL parameter metadata and the same data.
- Connector/J 8.0.15: MatrixOne still returns NULL for all tested parameters;
MySQL still returns non-NULL metadata.
- Correctness control: SELECT, INSERT, and UPDATE each returned/persisted the
expected integer, decimal, string, and binary values.
- Cleanup: each run drops its isolated database.
## Evidence
Representative MatrixOne output:
```text
filter-select: type=0,name=NULL | type=0,name=NULL; execution=pass
insert: type=0,name=NULL for all 5 parameters; execution=pass
update: type=0,name=NULL for all 5 parameters; execution=pass
```
The MySQL control reports concrete metadata for the same positions, including
BIGINT, DECIMAL, VARCHAR, and LONGBLOB.
## Code analysis
`pkg/sql/plan/visit_plan_rule.go` collects parameter positions in
`GetParamRule.applyExpr`, but its assignment to `mapTypes` is commented out.
`SetParamOrder` consequently emits zero-valued parameter types. The binary
prepare response in `pkg/frontend/mysql_protocol.go` converts those values to
`MYSQL_TYPE_NULL`. This is a confirmed data flow; the final fix should still
preserve supported inference rules for genuinely unconstrained markers.
## Regression coverage
After a fix, add a binary-protocol prepare regression covering typed filter,
INSERT, UPDATE, explicit cast, and unconstrained `SELECT ?` parameters. Check
both protocol metadata and a successful execution/data round trip.
## Related
Distinct from #27290, which concerns result-column metadata rather than input
parameter metadata.
Contributor guide
Assessment
This issue has not been assessed yet.