Skip to content

Check smallint columns against their signed or unsigned range - #800

Merged
staabm merged 1 commit into
phpstan:2.1.xfrom
Amoifr:smallint-integer-range
Oct 26, 2026
Merged

staabm merged 1 commit into
phpstan:2.1.xfrom
Amoifr:smallint-integer-range

Conversation

@Amoifr

@Amoifr Amoifr commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Closes #672

EntityColumnRule now knows that a smallint column can only hold int<-32768, 32767>, or int<0, 65535> when it is mapped with options: {unsigned: true}. A property typed with that range no longer gets "database can contain int but property expects int<-32768, 32767>", and a range that does not match the column (an unsigned range on a signed column, or the other way round) is reported.

I did it in the rule rather than in SmallIntType as suggested in the issue, because the descriptor does not see the column options: a fixed signed range there would also narrow DQL results, which would be wrong for unsigned MySQL columns. If you'd rather have the descriptor return int<-32768, 65535> too (correct for both), I'm happy to add it with a query result test.

The new test fails on 2.1.x with the error from the issue on 6 of its properties. I also checked by hand that the usual mutants on the new lines (instanceof, ??, === true, the ternary, each bound ±1) are all caught, since I couldn't run Infection locally. ODM tests were not run here (no ext-mongodb).

@staabm

staabm commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

looks like this repo needs a separate PR first to fix PHP 8.3 build.

could you look into it?

thank you.

@Amoifr
Amoifr force-pushed the smallint-integer-range branch from 40a1b10 to e17d412 Compare October 26, 2026 10:50
@Amoifr

Amoifr commented Oct 26, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @staabm! Looks like @ondrejmirtes beat me to it with #803 (I had landed on the same patch changes, so at least we agree 😄). I rebased this PR on top of it, so the build should be green now, including Mutation Testing.

@staabm
staabm requested a review from VincentLanglet October 26, 2026 11:19
@staabm

staabm commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

//cc @SanderMuller

@VincentLanglet
VincentLanglet requested a review from staabm October 26, 2026 13:37
@SanderMuller

Copy link
Copy Markdown
Contributor

I checked this locally with DBAL 3.10 and ORM 2.20. The reporter's attribute snippet is reported on 2.1.x and is clean with this PR. The new test fails on 2.1.x with the 6 errors from the description.

The change adds no new errors, because it only narrows the type the database can return. $signedAsUnsigned and $unsignedAsSigned were already reported on 2.1.x, and only their message changes. positive-int on a signed column and int<0, 255> on an unsigned column are still reported.

One small thing: DBAL 3 casts unsigned with (bool), so 'unsigned' => 1 creates an unsigned column that the rule treats as signed. (bool) ($fieldMapping['options']['unsigned'] ?? false) would match that. It does not block the PR.

I found no measurable performance difference. EntityColumnRuleTest takes 0.48 to 0.51 s of CPU on both sides.

@staabm
staabm merged commit 1ed9816 into phpstan:2.1.x Oct 26, 2026
51 checks passed
@staabm

staabm commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

thank you!

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.

False-positive of smallint type

4 participants