Skip to content

Conversation

@ramnes
Copy link
Contributor

@ramnes ramnes commented Dec 16, 2025

When bindStmtArgs parses binary protocol parameters, the MySQL type is available in paramTypes. However, the library loses this type information when passing the parsed values to the Handler.HandleStmtExecute callback: it converts length-encoded parameters (datetime, varchar, blob, etc.) to plain []byte and drops the type.

This creates problems for proxies: when forwarding these parameters to a backend, the client sees []byte and sends them as MYSQL_TYPE_STRING, even if the original type was MYSQL_TYPE_DATETIME or another type. Some server implementations strictly validate parameter types and reject this mismatch.

This PR introduces a simple TypedBytes struct that preserves the original MySQL type alongside the raw bytes. Handler.HandleStmtExecute callback now receives this struct instead of []byte for length-encoded parameters, and client.Stmt also handles TypedBytes by using the preserved type when sending to servers.

paramValues[i] = append(mysql.PutLengthEncodedInt(uint64(len(v))), v...)
case mysql.TypedBytes:
paramTypes[i] = []byte{v.Type}
paramValues[i] = append(mysql.PutLengthEncodedInt(uint64(len(v.Bytes))), v.Bytes...)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we directly use v.Bytes? Why need to encode it again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LengthEncodedString in server/stmt.go strips the length prefix when parsing. v.Bytes contains only the raw data, so we need to re-add the length prefix when sending.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants