Skip to content

fix(mysql): don't infer u8 for YEAR columns in query!/query_as! - #4447

Open
flawand wants to merge 2 commits into
transact-rs:mainfrom
flawand:fix/mysql-year-type-inference
Open

flawand wants to merge 2 commits into
transact-rs:mainfrom
flawand:fix/mysql-year-type-inference

Conversation

@flawand

@flawand flawand commented Oct 8, 2026 •

Copy link
Copy Markdown

Summary

  • YEAR's value domain is 0 or 1901..=2155, which doesn't fit in u8. uint_compatible() in sqlx-mysql/src/types/uint.rs treated ColumnType::Year as compatible with every unsigned integer type (u8, u16, u32, u64), and since the query!/query_as! macros infer a default Rust type by scanning the declared type list in order and picking the first compatible() match, u8 (listed first) always won — causing a runtime decode error (out of range integral type conversion attempted) for any realistic year value.
  • u8 is now excluded from matching YEAR columns via a new uint_non_year_compatible() check, so default inference falls through to u16 (the next candidate, and the smallest type that can hold the full YEAR range). As a side effect, an explicit : u8 override on a YEAR column is now also a compile-time error instead of a silent runtime failure.

Fixes #4358

Test plan

  • Added macro_infer_year_type to tests/mysql/macros.rs, reproducing the issue against a live MariaDB 11.8 instance: before the fix it failed with the exact error from the issue (out of range integral type conversion attempted); after the fix it passes and prints the correctly-decoded year.
  • cargo check -p sqlx-mysql passes.

fadilawand and others added 2 commits October 7, 2026 23:01
`YEAR`'s value domain is `0` or `1901..=2155`, which doesn't fit in `u8`.
`uint_compatible()` treated `YEAR` as compatible with every unsigned
integer type, so the macros' default type inference (which scans types
in declaration order and picks the first match) always picked `u8`,
causing a runtime decode error for any realistic year value. `u8` is
now excluded, so inference falls through to `u16`, `u32`, or `u64`.

Fixes transact-rs#4358

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The test added in the previous commit needs this table to exist in the
database *before* compilation, since query!/query_as! introspect live
schema at compile time. It was missing from tests/mysql/setup.sql, so
CI's fresh database didn't have it and the macro failed with
"Table 'sqlx.macro_infer_year_type' doesn't exist".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

Runtime decoding error when mapping MariaDB YEAR/SMALLINT to u16 using query_as!

1 participant