matrixorigin / matrixorigin/matrixone

[Bug]: server-prepared ParameterMetaData reports NULL for all parameters

Open
#27,328 0 comments 0 reactions 1 assignee Claimed by @jiangxinmeng1 View on GitHub
kind/bug needs-triage
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

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.