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 calling refresh on an entity, under certain circumstances the id used to fetch the entity from the database can be wrong.
Current behavior
Confusing the UnitOfWork by creating a new entity with the same id as one that it is already being managed can cause OID collisions when that entity is garbage collected due to not having a reference in the UnitOfWork's identityMap. This leads to a refresh attempting to use the wrong id in the database.
How to reproduce
#[Entity]
#[Table("my_entity")]
class MyEntity
{
#[Id, Column(name: "id", type: "integer"), GeneratedValue(strategy: 'SEQUENCE')]
public ?int$id = null;
}
#[Entity]
#[Table("my_token")]
class MyToken
{
publicfunction__construct(
#[Id, Column(name: "hash", type: "string")]
publicstring$hash,
) {}
}
// NOTE: Seed the database with a single my_token$key = md5(random_bytes(4));
$em->getConnection()->executeStatement(<<<SQL DELETE FROM my_token; INSERT INTO my_token VALUES ('{$key}');SQL);
functionrefreshMyToken(EntityManager$em): void
{
global$key;
$token = $em->find(MyToken::class, $key);
echo"MyToken (original) has oid of ".spl_object_id($token)."\n";
// NOTE: This causes all the problems, as the UnitOfWork still thinks the token is active and managed$em->createQuery('DELETE FROM MyToken s')->execute();
$token = newMyToken($key);
// NOTE: This causes the deprecation warning in addToIdentityMap, but continues$em->persist($token);
$em->flush();
echo"MyToken (new) has oid of ".spl_object_id($token)."\n";
gc_collect_cycles();
}
refreshMyToken($em);
$entity = newMyEntity();
$em->persist($entity);
$em->flush();
echo"Entity has oid of ".spl_object_id($entity)."\n";
\Closure::fromCallable(
/** @psalm-suppress InaccessibleProperty */function() {
/** @var \Doctrine\ORM\UnitOfWork $this */echo"UnitOfWork identifier map is: ".var_export($this->entityIdentifiers, true)."\n";
},
)->call($em->getUnitOfWork());
$em->refresh($entity);
Output:
MyToken (original) has oid of 769
MyToken (new) has oid of 765
Entity has oid of 765
UnitOfWork identifier map is: array (
769 =>
array (
'hash' => 'b8ff315c79068f22ccf4543cd93f9f46',
),
765 =>
array (
'hash' => 'b8ff315c79068f22ccf4543cd93f9f46',
),
)
Fatal error: Uncaught PDOException: SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type integer: "b8ff315c79068f22ccf4543cd93f9f46"
Expected behavior
In the future the exception in #10785 will be thrown, but currently the code continues as normal in a broken state until the mismatched column types stop execution.
The text was updated successfully, but these errors were encountered:
Bug Report
Summary
When calling refresh on an entity, under certain circumstances the id used to fetch the entity from the database can be wrong.
Current behavior
Confusing the
UnitOfWork
by creating a new entity with the same id as one that it is already being managed can cause OID collisions when that entity is garbage collected due to not having a reference in theUnitOfWork
'sidentityMap
. This leads to arefresh
attempting to use the wrong id in the database.How to reproduce
Output:
Expected behavior
In the future the exception in #10785 will be thrown, but currently the code continues as normal in a broken state until the mismatched column types stop execution.
The text was updated successfully, but these errors were encountered: