Skip to content

Use VarString for string parameter encoding in binary protocol#142

Open
webpatser wants to merge 3 commits intoamphp:3.xfrom
webpatser:fix/string-parameter-type-for-mariadb-uuid
Open

Use VarString for string parameter encoding in binary protocol#142
webpatser wants to merge 3 commits intoamphp:3.xfrom
webpatser:fix/string-parameter-type-for-mariadb-uuid

Conversation

@webpatser
Copy link
Copy Markdown

Summary

  • String parameters in prepared statements are currently encoded as MYSQL_TYPE_LONG_BLOB (0xfb), which tells the server to treat values as raw binary data
  • This breaks MariaDB's native UUID column type (introduced in MariaDB 10.7), which requires string-typed parameters to trigger string→UUID parsing
  • Changes the type to MYSQL_TYPE_VAR_STRING (0xfd), which is more semantically correct for PHP string values and matches MySQL's own C API behavior for string binds

Why this matters

MariaDB 10.7+ introduced a native UUID column type that stores UUIDs as 16-byte binary internally. When a prepared statement parameter is typed as LONG_BLOB, MariaDB interprets the 36-byte ASCII UUID string as raw bytes instead of parsing the human-readable format. With VAR_STRING, MariaDB correctly converts the string representation to its internal format.

Safety

The wire encoding (length-prefixed bytes) is identical for both LongBlob and VarString — only the 2-byte type header in COM_STMT_EXECUTE changes. All existing tests pass (136/136).

This is effectively a no-op for all standard MySQL/MariaDB column types (VARCHAR, CHAR, TEXT, BLOB, etc.) since both types trigger the same implicit conversion paths. The difference only surfaces for MariaDB-specific types like UUID that distinguish between string and binary parameter sources.

Suggestion

The current test suite only runs against MySQL. Adding MariaDB to the CI matrix (related: #80) would help catch driver-specific issues like this. Happy to help with that in a follow-up PR if there's interest.

String parameters in prepared statements were encoded with
MYSQL_TYPE_LONG_BLOB (0xfb), which tells the server to treat
the value as raw binary data. This breaks MariaDB's native UUID
column type (introduced in 10.7), which requires the parameter
to be declared as a string type to trigger string-to-UUID parsing.

Changing to MYSQL_TYPE_VAR_STRING (0xfd) is more semantically
correct for PHP string values and matches what MySQL's own C API
uses for string binds. The wire encoding (length-prefixed bytes)
is identical for both types, so this is a no-op for all standard
column types on both MySQL and MariaDB.
Psalm 6.15.1 on PHP 8.4.19 incorrectly reports InvalidAttribute
for #[\Override] attributes. This was green on PHP 8.4.18 but
broke with the runner update. Suppress until Psalm is updated.
@webpatser
Copy link
Copy Markdown
Author

Note: The CI failures on PHP 8.2–8.5 are unrelated to this change — Psalm 6.15.1 started reporting InvalidAttribute for #[\Override] after the GitHub runner updated to PHP 8.4.19 (8.4.18 was green). The actual test suite passes on all PHP versions.

webpatser added a commit to webpatser/fledge-fiber that referenced this pull request Apr 10, 2026
Security:
- Fix HTTP/2 ping flood on active streams (amphp/http-server#386)

Bug fixes:
- Use VarString for string params in binary protocol (amphp/mysql#142)
- Decode BIT columns as int instead of string (amphp/mysql#138)
- Close connections on pool destruct (amphp/http-client#396)
- Fix duplicate keys in byte-stream split() (amphp/byte-stream#113)
- Fix Closure type annotation for static analysis (amphp/amp#451)
- Safely handle DisposedException on unsubscribe (amphp/redis#100)

Features:
- Add TLS support for Redis connections (amphp/redis#98)
- Add disperse() for concurrent closure execution (amphp/amp#460)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant