-
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
Wrong commit order in some relation cases #7006
Comments
This requires a reproducible/minimal test case before the Also, do you think that a unit test case can be made around |
I didn't fix it. In fact I've just rollback CommitOrderCalculator class to its previous version by functionality. |
I'm also getting this error but really struggling to produce a minimal test case. Still trying |
I have this too. I debugged the flush call and commit order calculation seems to be wrong (for whatever reason). Went back to 2.5.14 and the problem disappeared. I was using nelmio/alice to populate a test database and \Doctrine\ORM\UnitOfWork::getCommitOrder seems to return wrong order. I don't believe alice has anything to do with the issue though. My case shortly: Sorry I cannot help more at he the moment. Just "me too" really. |
<?php
include '../vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php';
$calc = new \Doctrine\ORM\Internal\CommitOrderCalculator();
$classPCT = json_decode('{"name":"PCT","namespace":"","rootEntityName":"PCT","customGeneratorDefinition":null,"customRepositoryClassName":null,"isMappedSuperclass":false,"isEmbeddedClass":false,"parentClasses":[],"subClasses":[],"embeddedClasses":[],"namedQueries":[],"namedNativeQueries":[],"sqlResultSetMappings":[],"identifier":["id"],"inheritanceType":1,"generatorType":5,"fieldMappings":{"id":{"fieldName":"id","type":"integer","scale":0,"length":null,"unique":false,"nullable":false,"precision":0,"id":true,"columnName":"id"}},"fieldNames":{"id":"id"},"columnNames":{"id":"id"},"discriminatorValue":null,"discriminatorMap":[],"discriminatorColumn":null,"table":{"name":"pct"},"lifecycleCallbacks":[],"entityListeners":[],"associationMappings":{"book":{"fieldName":"book","joinColumns":[{"name":"bookingId","unique":false,"nullable":false,"onDelete":null,"columnDefinition":null,"referencedColumnName":"id"}],"cascade":[],"inversedBy":null,"targetEntity":"Book","fetch":2,"type":2,"mappedBy":null,"isOwningSide":true,"sourceEntity":"PCT","isCascadeRemove":false,"isCascadePersist":false,"isCascadeRefresh":false,"isCascadeMerge":false,"isCascadeDetach":false,"sourceToTargetKeyColumns":{"bookingId":"id"},"joinColumnFieldNames":{"bookingId":"bookingId"},"targetToSourceKeyColumns":{"id":"bookingId"},"orphanRemoval":false},"fees":{"fieldName":"fees","mappedBy":"pct","targetEntity":"PCTFee","cascade":["persist","remove"],"orphanRemoval":false,"fetch":2,"orderBy":{"id":"ASC"},"type":4,"inversedBy":null,"isOwningSide":false,"sourceEntity":"PCT","isCascadeRemove":true,"isCascadePersist":true,"isCascadeRefresh":false,"isCascadeMerge":false,"isCascadeDetach":false}},"isIdentifierComposite":false,"containsForeignIdentifier":false,"idGenerator":{},"sequenceGeneratorDefinition":null,"tableGeneratorDefinition":null,"changeTrackingPolicy":1,"isVersioned":null,"versionField":null,"cache":null,"reflClass":{"name":"PCT"},"isReadOnly":false,"reflFields":{"id":{"name":"id","class":"PCT"},"book":{"name":"book","class":"PCT"},"fees":{"name":"fees","class":"PCT"}}}');
$calc->addNode($classPCT->name, $classPCT);
$classPCTFee = json_decode('{"name":"PCTFee","namespace":"","rootEntityName":"PCTFee","customGeneratorDefinition":null,"customRepositoryClassName":null,"isMappedSuperclass":false,"isEmbeddedClass":false,"parentClasses":[],"subClasses":[],"embeddedClasses":[],"namedQueries":[],"namedNativeQueries":[],"sqlResultSetMappings":[],"identifier":["id"],"inheritanceType":1,"generatorType":4,"fieldMappings":{"id":{"fieldName":"id","type":"integer","scale":0,"length":null,"unique":false,"nullable":false,"precision":0,"id":true,"columnName":"id"}},"fieldNames":{"id":"id"},"columnNames":{"id":"id"},"discriminatorValue":null,"discriminatorMap":[],"discriminatorColumn":null,"table":{"name":"pct_fee"},"lifecycleCallbacks":[],"entityListeners":[],"associationMappings":{"pct":{"fieldName":"pct","joinColumns":[{"name":"paymentCardTransactionId","unique":false,"nullable":false,"onDelete":null,"columnDefinition":null,"referencedColumnName":"id"}],"cascade":[],"inversedBy":"fees","targetEntity":"PCT","fetch":2,"type":2,"mappedBy":null,"isOwningSide":true,"sourceEntity":"PCTFee","isCascadeRemove":false,"isCascadePersist":false,"isCascadeRefresh":false,"isCascadeMerge":false,"isCascadeDetach":false,"sourceToTargetKeyColumns":{"paymentCardTransactionId":"id"},"joinColumnFieldNames":{"paymentCardTransactionId":"paymentCardTransactionId"},"targetToSourceKeyColumns":{"id":"paymentCardTransactionId"},"orphanRemoval":false}},"isIdentifierComposite":false,"containsForeignIdentifier":false,"idGenerator":{},"sequenceGeneratorDefinition":null,"tableGeneratorDefinition":null,"changeTrackingPolicy":1,"isVersioned":null,"versionField":null,"cache":null,"reflClass":{"name":"PCTFee"},"isReadOnly":false,"reflFields":{"id":{"name":"id","class":"PCTFee"},"pct":{"name":"pct","class":"PCTFee"}}}');
$calc->addNode($classPCTFee->name, $classPCTFee);
$classBook = json_decode('{"name":"Book","namespace":"","rootEntityName":"Book","customGeneratorDefinition":null,"customRepositoryClassName":null,"isMappedSuperclass":false,"isEmbeddedClass":false,"parentClasses":[],"subClasses":[],"embeddedClasses":[],"namedQueries":[],"namedNativeQueries":[],"sqlResultSetMappings":[],"identifier":["id"],"inheritanceType":1,"generatorType":5,"fieldMappings":{"id":{"fieldName":"id","type":"integer","scale":0,"length":null,"unique":false,"nullable":false,"precision":0,"id":true,"columnName":"id"},"exchangeCode":{"fieldName":"exchangeCode","type":"string","scale":0,"length":255,"unique":false,"nullable":true,"precision":0,"columnName":"exchangeCode"}},"fieldNames":{"id":"id","exchangeCode":"exchangeCode"},"columnNames":{"id":"id","exchangeCode":"exchangeCode"},"discriminatorValue":null,"discriminatorMap":[],"discriminatorColumn":null,"table":{"name":"book"},"lifecycleCallbacks":[],"entityListeners":[],"associationMappings":{"paymentCardTransaction":{"fieldName":"paymentCardTransaction","targetEntity":"PCT","joinColumns":[{"name":"paymentCardTransactionId","unique":true,"nullable":true,"onDelete":null,"columnDefinition":null,"referencedColumnName":"id"}],"mappedBy":null,"inversedBy":null,"cascade":["persist","remove"],"orphanRemoval":false,"fetch":2,"type":1,"isOwningSide":true,"sourceEntity":"Book","isCascadeRemove":true,"isCascadePersist":true,"isCascadeRefresh":false,"isCascadeMerge":false,"isCascadeDetach":false,"sourceToTargetKeyColumns":{"paymentCardTransactionId":"id"},"joinColumnFieldNames":{"paymentCardTransactionId":"paymentCardTransactionId"},"targetToSourceKeyColumns":{"id":"paymentCardTransactionId"}}},"isIdentifierComposite":false,"containsForeignIdentifier":false,"idGenerator":{},"sequenceGeneratorDefinition":null,"tableGeneratorDefinition":null,"changeTrackingPolicy":1,"isVersioned":null,"versionField":null,"cache":null,"reflClass":{"name":"Book"},"isReadOnly":false,"reflFields":{"id":{"name":"id","class":"Book"},"exchangeCode":{"name":"exchangeCode","class":"Book"},"paymentCardTransaction":{"name":"paymentCardTransaction","class":"Book"}}}');
$calc->addNode($classBook->name, $classBook);
$calc->addDependency($classPCT->name, $classBook->name, 0);
$calc->addDependency($classPCT->name, $classPCTFee->name, 1);
$calc->addDependency($classBook->name, $classPCT->name, 1);
$result = $calc->sort();
$okSortedClasses = ['PCT', 'PCTFee', 'Book'];
$rightOrder = implode(',', $okSortedClasses);
foreach ($result as $class) {
$okClassName = array_shift($okSortedClasses);
if ($class->name !== $okClassName) {
echo 'Wrong class commit order! Should be: '.$rightOrder.'. Got: '.implode(',', array_map(function ($item) {return $item->name;}, $result));
break;
}
}
|
@contentrail awesome, could you turn that into a unit test and send a PR? |
@bendavies that's a functional test, I've asked for a unit test (since @contentrail isolated the cause of the bug) |
After a upgrade, this affects us too - was a pain to find it! I just have to say: |
@someother1 the project is active and maintained: if you need this to be fixed then remembered that this is open source, and fixes come from contributors first. |
This looks similar to #7259 which is fixed in |
@Majkl578 I can confirm that After setup new instance of $em->persist($address);
$em->persist($household);
$em->persist($person); When I try to flush, the commit order is
Exception by $em->persist($household);
$em->persist($address);
$em->persist($person); Then it fails on Do you guys have any more info about? There're many issues about that, should I discuss somewhere else? |
Please help – try #10547 and report if it fixes the issue |
Add test to show #7006 has been fixed
Issue was found after updating to v.2.6 and associated with improvements in CommitOrderCalculator class.
Here is the example to reproduce.
Objects:
Book has optional relation to the PCT object. Some Bookes has PCT and some not. But all PCT has relation to Book.
How to reproduce:
Find one Book (or create new).
Create new PCT object with even one PCTFee object for this Book object.
Try to flush.
Error:
I've try to figure out why and found that CommitOrderCalculator produce wrong commit order: PCTFee, Book, PCT.
It's wrong because PCTFee depends on PCT - PCT must be saved earlier.
New code in CommitOrderCalculator uses weights of relations. But weights is wrong.
We have 2 relations with different weights (nullable and not nullable):
Before version 2.6 CommitOrderCalculator has checked both relations. But now it checks only relation with maximum weight!
I've removed code using weights from CommitOrderCalculator:
and bug has disappeared.
The text was updated successfully, but these errors were encountered: