Skip to content

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

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

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>
@flawand

flawand commented Oct 21, 2026

Copy link
Copy Markdown
Author

Hi @abonander 👋

This PR fixes #4358, but the issue was closed on Oct 19 by its author. They had mentioned earlier that the error disappeared for them after they split their project into multiple crates, so I think they closed it because they stopped hitting the bug, not because it was fixed.

The bug is still present on main. I reproduced it before applying this change. ColumnType::Year is treated as compatible with u8, and query!/query_as! pick the first compatible type, so YEAR columns are inferred as u8. That fails at runtime with out of range integral type conversion attempted for any realistic year value (1901..=2155).

This PR excludes u8 for YEAR, so inference falls through to u16. It includes a regression test (macro_infer_year_type) that fails without the fix and passes with it.

Could you take a look when you have time? If you agree the issue is still valid, it may also be worth reopening #4358 so it gets tracked. I'm happy to make changes.

@abonander

Copy link
Copy Markdown
Collaborator

This PR is not mergeable due to our newly codified AI policy: #4472

Please feel free to open a new PR with the issues addressed.

@abonander abonander closed this Oct 22, 2026
@flawand

flawand commented Oct 22, 2026

Copy link
Copy Markdown
Author

@abonander I understand the idea of your policy, it makes sense, and I am glad you have that policy given how important it is in the current times we are in, but please ask before making assumptions that I vibe coded it and committed the code without review or serious time/effort. I spent serious time reviewing every line Claude added, deleted the code, then manually added it myself to ensure the code works and I learnt something in order to build myself to bigger issues/features.

Also, I am still relatively new to Rust production code. So the few lines changed took some time to figure out given everything going on in the code base.

Lastly, feel free to quiz me on the code in the PR. I am happy to have my knowledge tested. It will be a great way to confirm I know what I am doing!

Good luck on your mission with AI and I wish you the best of luck.

@abonander

Copy link
Copy Markdown
Collaborator

You're assuming my state of mind in closing this PR. Please carefully re-read the policy:

Instead, we reserve the right to refuse contributions for any reason, including but not limited to:
[...]

  • Submitting commits attributed to an AI agent, such as Claude;

Bottom line, I don't want commits co-authored by Claude in the repository. That's free advertising for a company I personally consider to be doing active, measurable harm, and a loud and clear signal to users that AI-generated code is leaking into the project.

I apologize for using a copy-pasted message, but I had at least a dozen PRs to close for similar reasons.

@flawand

flawand commented Oct 22, 2026

Copy link
Copy Markdown
Author

@abonander understood and fair points. Apologies if my comment came across as personal, I didn’t mean to make assumptions about you.
If I recreate the PR of a new branch with manual commits and mention AI usage in the PR description for transparency, would that suffice?

@abonander

Copy link
Copy Markdown
Collaborator

You don't need to mention AI. I don't care and I'd really rather not know, but I'm not going to ban a PR just for mentioning it as long as it's not Claude that actually wrote it.

@flawand
flawand deleted the fix/mysql-year-type-inference branch October 24, 2026 15:49
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!

2 participants