You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using any version of ORM with DBAL 3.x, an entity with a column type bigint and a property type int is incorrectly treated as changed every time it is used. This causes high volumes of unexpected database writes (and listener invocations).
Prior to 2.19.4, orm:validate-schema would report that the column type and property type were incompatible. That was changed in #11414 to fix #11377 - as a result doctrine no longer warns about this issue.
I reported this at the time, but I think as we were discussing on a closed PR (and I didn't get a chance to follow up) it has been overlooked.
When I run doctrine orm:validate-schema the schema validates successfully.
If I then run code like:
// assuming an entity in the database with an id=1, number=20$entity = $entity_manager->getRepository(MyEntity::class)->find('1');
$entity_manager->flush();
And examine the queries from my database logs, I can see two queries:
ORM's UnitOfWork::computeChangeSet checks whether {original value returned by dbal} === {current value of entity property} - that link is for 2.x, but the logic is the same in 3.x and 4.x
If the entity property is typed int then PHP has automatically typecast '15' to 15 when hydrating the object.
This means that the UnitOfWork checks '15' === 15, this does not match, so the entity is added to the changeset and marked for update.
Expected behavior
Either:
The UnitOfWork should not treat the entity as changed
Or the schema validation tool should report that the column and property types are incompatible.
How to reproduce
I have not created a failing test because the correct test depends on how you would prefer to solve this.
I believe that the reproduction is clear from the description and links to how the implementations cause this bug, but am happy to create an official reproduction if it would help.
Proposed fix
IMHO the best solution is probably to fix this directly in the UnitOfWork, to allow people to type properties correctly and eliminate the unnecessary writes.
The === comparison appears in both computeChangeSet and recomputeSingleEntityChangeSet.
I would suggest therefore extracting a method something like:
privatefunctionisValueChanged(mixed$original, mixed$actual): bool
{
if (is_int($actual) && is_string($original)) {
// it is always safe to cast int to string, it's not guaranteed safe the other way roundreturn$original === (string) $actual;
}
// there may be scope to support other type differences here in futurereturn$original === $actual;
}
If this is acceptable I can work on a PR with implementation and tests.
The text was updated successfully, but these errors were encountered:
Bug Report
Summary
When using any version of ORM with DBAL 3.x, an entity with a column type
bigint
and a property typeint
is incorrectly treated as changed every time it is used. This causes high volumes of unexpected database writes (and listener invocations).Prior to 2.19.4,
orm:validate-schema
would report that the column type and property type were incompatible. That was changed in #11414 to fix #11377 - as a result doctrine no longer warns about this issue.I reported this at the time, but I think as we were discussing on a closed PR (and I didn't get a chance to follow up) it has been overlooked.
Current behavior
Given an entity like:
When I run
doctrine orm:validate-schema
the schema validates successfully.If I then run code like:
And examine the queries from my database logs, I can see two queries:
SELECT FROM my_entity WHERE id = 1
UPDATE my_entity SET number = 20 WHERE id = 1
.This happens because:
bigint
is hydrated as a string{original value returned by dbal} === {current value of entity property}
- that link is for 2.x, but the logic is the same in 3.x and 4.xint
then PHP has automatically typecast'15'
to15
when hydrating the object.'15' === 15
, this does not match, so the entity is added to the changeset and marked for update.Expected behavior
Either:
How to reproduce
I have not created a failing test because the correct test depends on how you would prefer to solve this.
I believe that the reproduction is clear from the description and links to how the implementations cause this bug, but am happy to create an official reproduction if it would help.
Proposed fix
IMHO the best solution is probably to fix this directly in the UnitOfWork, to allow people to type properties correctly and eliminate the unnecessary writes.
The
===
comparison appears in bothcomputeChangeSet
andrecomputeSingleEntityChangeSet
.I would suggest therefore extracting a method something like:
If this is acceptable I can work on a PR with implementation and tests.
The text was updated successfully, but these errors were encountered: