-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid an inconsistency in topological sort result order #11086
Conversation
4087e44
to
5876b4d
Compare
69a03ed
to
7d04e33
Compare
This PR changes a detail in the commit order computation for depended-upon entities. We have a parent-child relationship between two entity classes. The association is parent one-to-many children, with the child entities containing the (owning side) back-reference. Cascade-persist is not used, so all entities have to be passed to `EntityManager::persist()`. Before v2.16.0, two child entities C1 and C2 will be inserted in the same order in which they are passed to `persist()`, and that is regardless of whether the parent entity was passed to `persist()` before or after the child entities. As of v2.16.0, passing the parent entity to `persist()` _after_ the child entities will lead to an insert order that is _reversed_ compared to the order of `persist()` calls. This PR makes the order consistent in both cases, as it was before v2.16.0. #### Cause When the parent is passed to `persist()` after the children, commit order computation has to re-arrange the entities. The parent must be inserted first since it is referred to by the children. The implementation of the topological sort from doctrine#10547 processed entities in reverse `persist()` order and unshifted finished nodes to an array to obtain the final result. That leads to dependencies (parent → before c1, parent → before c2) showing up in the result in the reverse order of which they were added. This PR changes the topological sort to produce a result in the opposite order ("all edges pointing left"), which helps to avoid the duplicate array order reversal. #### Discussion * This PR _does not_ change semantics of the `persist()` so that entities would (under all ciscumstances) be inserted in the order of `persist()` calls. * It fixes an unnecessary inconsistency between versions before 2.16.0 and after. In particular, it may be surprising that the insert order for the child entities depends on whether another referred-to entity (the parent) was added before or after them. * _Both_ orders (c1 before or after c2) are technically and logically correct with regard to the agreement that `commit()` is free to arrange entities in a way that allows for efficient insertion into the database. Fixes doctrine#11058.
7d04e33
to
108fa30
Compare
Thanks @mpdude ! |
@mpdude Thank you for the PR! Sorry for the late reply. Anyway. When I look Again, thank you for the effort and have a great holidays! |
Kind sir, just wanted to say that you are a legend. |
This PR changes a detail in the commit order computation for depended-upon entities.
We have a parent-child relationship between two entity classes. The association is parent one-to-many children, with the child entities containing the (owning side) back-reference.
Cascade-persist is not used, so all entities have to be passed to
EntityManager::persist()
.Before v2.16.0, two child entities C1 and C2 will be inserted in the same order in which they are passed to
persist()
, and that is regardless of whether the parent entity was passed topersist()
before or after the child entities.As of v2.16.0, passing the parent entity to
persist()
after the child entities will lead to an insert order that is reversed compared to the order ofpersist()
calls.This PR makes the order consistent in both cases, as it was before v2.16.0.
Cause
When the parent is passed to
persist()
after the children, commit order computation has to re-arrange the entities. The parent must be inserted first since it is referred to by the children.The implementation of the topological sort from #10547 processed entities in reverse
persist()
order and unshifted finished nodes to an array to obtain the final result. That leads to dependencies (parent → before c1, parent → before c2) showing up in the result in the reverse order of which they were added.This PR changes the topological sort to produce a result in the opposite order ("all edges pointing left"), which helps to avoid the duplicate array order reversal.
Discussion
persist()
so that entities would (under all ciscumstances) be inserted in the order ofpersist()
calls.commit()
is free to arrange entities in a way that allows for efficient insertion into the database.GH11058Test
test case added, note that there is nothing that guarantees any particular order of the child entities within the parent'sCollection
. Also, the order of child entities in the collection is not relevant for the commit order computation, since the collection is not the owning side and no cascade-persist is used.persist()
in the order in which they are found in the collection. So, they would be inserted in collection order unless they'd explicitly be passed topersist()
before. Bottom line: Do not rely on collection ordering unless it's explicitly defined, e. g. with an explicitrank
field.Fixes #11058.