mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
[PR #10566] Commit order for removals has to consider SET NULL, not nullable
#12458
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Original Pull Request: https://github.com/doctrine/orm/pull/10566
State: closed
Merged: Yes
When computing the commit order for entity removals, we have to look out for
@ORM\JoinColumn(onDelete="SET NULL")to find places where cyclic associations can be broken.This is part of the efforts in #10547 to solve various commit-order related problems.
Background
The UoW computes a "commit order" to find the sequence in which tables shall be processed when inserting entities into the database or performing delete operations.
For the insert case, the ORM is able to schedule extra updates that will be performed after all entities have been inserted. Associations which are configured as
@ORM\JoinColumn(nullable=true, ...)can be left asNULLin the database when performing the initialINSERTstatements, and will be updated once all new entities have been written to the database. This can be used to break cyclic associations between entity instances.For removals, the ORM does not currently implement up-front
UPDATEstatements toNULLout associations beforeDELETEstatements are executed. That means when associations form a cycle, users have to configure@ORM\JoinColumn(onDelete="SET NULL", ...)on one of the associations involved. This transfers responsibility to the DBMS to break the cycle at that place.But, we still have to perform the delete statements in an order that makes this happen early enough. This may be a different order than the one required for the insert case. We can find it only by looking at the
onDeletebehaviour. We must ignore thenullableproperty, which is irrelevant, since we do not even try toNULLanything.Example
Assume three entity classes
A,B,C. There are unidirectional one-to-one associationsA -> B,B -> C,C -> A. All those associations arenullable= true.Three entities
$a,$b,$care created from these respective classes and associations are set up.All operations
cascadeat the ORM level. So we can test what happens when we start the operations at the three individual entities, but in the end, they will always involve all three of them.Any insert order will work, so the improvements necessary to solve #10531 or #10532 are not needed here. Since all associations are between different tables, the current table-level computation is good enough.
For the removal case, only the
A -> Bassociation hasonDelete="SET NULL". So, the only possible execution order is$b,$c,$a. We have to find that regardless of where we start the cascade operation.The DBMS will set the
A -> Bassociation on$atoNULLwhen we remove$b. We can then remove$csince it is no longer being referred to, then$a.Related cases
These cases ask for the ORM to perform the extra update before the delete by itself, without DBMS-level support:
Extra bonus
This is what the DALL·E AI thinks it looks like when the UnitOfWork is sequencing entity deletions with cascade.