fix: compare entity ids of mixed string/number type as equal - #12780
fix: compare entity ids of mixed string/number type as equal#12780Arul1998 wants to merge 4 commits into
Conversation
OrmUtils.compareIds only short-circuited when both ids shared the same primitive type (both string or both number). Drivers such as MySQL return bigint columns as strings, so a persisted id can be "1" on the DB-loaded side and 1 in memory. The mismatched pair matched no branch and fell through to a false result, making the relation look removed and nulling its FK on save. Compare single-id maps by their string form when the two types differ, so "1" still matches 1. Same-type comparisons are unchanged. Fixes typeorm#11773
Code Review by Qodo
1. Unsafe integer id coercion
|
Code Review by Qodo
1. Issue #11773 only unit-tested
|
Guard the string/number id path so NaN and Infinity are not coerced to match a "NaN"/"Infinity" string. Add unit tests for the non-finite and null id cases.
…ul1998/typeorm into fix/compare-ids-bigint-string
Description of change
What this does: Makes
OrmUtils.compareIdstreat a single-idmap as equalwhen the two ids hold the same value but different primitive types — e.g.
"1"(string) and
1(number).Why it's needed:
compareIdsonly short-circuited when both ids shared thesame primitive type (both string or both number). Drivers such as MySQL return
bigintcolumns as strings, so a persisted id can be"1"on the DB-loaded sideand
1in memory. That mismatched pair matched no branch and fell through to afalseresult (deepCompare→compare2Objectsalso only string-normalizessame-type primitives). As a result
OneToManySubjectBuildersaw the child asorphaned and nulled its FK on save (#11773).
The change: In the single-
idfast path, when the two id types differ, fallback to comparing
String(firstId.id) === String(secondId.id). Same-typecomparisons are unchanged (still
firstId.id === secondId.id). The change isscoped to entity-id comparison — the general-purpose
compare2Objectsis leftuntouched to avoid affecting jsonb/object diffing elsewhere.
How it was verified: Added a
compareIdsunit-test block(
test/unit/util/orm-utils.test.ts) covering same-type equality, string-vs-numberequality (
"1"===1), unequal string/number stayingfalse, null/undefinedhandling, and the composite-id
deepComparefallback. The full file passes 32/32.Note for maintainers: composite / non-
idprimary keys still route throughdeepCompareand aren't covered by this narrow fix. If you'd prefer to solve thewhole class of driver type-coercion (e.g. normalizing
bigintto a consistentstring at the driver level), happy to take that direction instead.
Pull-Request Checklist
masterbranchFixes #11773test/unit/util/orm-utils.test.ts)docs/docs/**.md) — N/A (internal comparison fix, no public API/doc change)