Skip to content
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

Changeset with the field date is lost in some edge cases #2538

Open
olivier34000 opened this issue Jun 15, 2023 · 2 comments
Open

Changeset with the field date is lost in some edge cases #2538

olivier34000 opened this issue Jun 15, 2023 · 2 comments
Labels

Comments

@olivier34000
Copy link

olivier34000 commented Jun 15, 2023

BC Break Report

Q A
BC Break yes
Version 2.1

Summary

When we have a field with the type date if the field is updated in less than 1 second the update does not work correctly. The field is not updated

Previous behavior

In this previous version when the field was a date we compared 2 MongoDate
https://github.com/doctrine/mongodb-odm/blob/1.3.x/lib/Doctrine/ODM/MongoDB/UnitOfWork.php#L816-L823

In the MongoDate object we have a timestamp and the miliseconds.

In the new version we have https://github.com/doctrine/mongodb-odm/blob/2.6.x/lib/Doctrine/ODM/MongoDB/UnitOfWork.php#L798-L809

The UTCDateTime object contains also the milliseconds but we loose this information in the changeSet.

Is-it possible to only cast the UTCDateTime in string in order to keep this information ?

The code should be

                // skip equivalent date values
                if (isset($class->fieldMappings[$propName]['type']) && $class->fieldMappings[$propName]['type'] === 'date') {
                    /** @var DateType $dateType */
                    $dateType      = Type::getType('date');
                    $dbOrgValue    = $dateType->convertToDatabaseValue($orgValue);
                    $dbActualValue = $dateType->convertToDatabaseValue($actualValue);

                    $orgMillisec    = $dbOrgValue instanceof UTCDateTime ? (string) $dbOrgValue : null;
                    $actualMillsec = $dbActualValue instanceof UTCDateTime ? (string) $dbActualValue : null;

                    if ($orgMillisec === $actualMillsec) {
                        continue;
                    }
                }
@malarzm
Copy link
Member

malarzm commented Jun 16, 2023

According to docs casting to string will not be enough as it'll get us timestamp again.

@alcaeus do you remember the reason why we're casting values to anything instead of relying on $dbOrgValue == $dbActualValue?

@malarzm malarzm added the Bug label Jun 16, 2023
@malarzm malarzm added this to the 2.5.3 milestone Jun 16, 2023
@alcaeus
Copy link
Member

alcaeus commented Jun 16, 2023

@alcaeus do you remember the reason why we're casting values to anything instead of relying on $dbOrgValue == $dbActualValue?

Off the top of my head, no.

The code should be [...]

While casting to string will indeed give us a string with millisecond precision, this shouldn't be necessary and comparing the UTCDateTime instances directly is the way to go as the class implements a compare handler. @olivier34000 if you'd like, you can create a PR (ideally with a failing test case) to change this. No need to cast to milliseconds, just comparing $dbOrgValue == $dbActualValue should be sufficient. Just keep in mind to use a loose comparison, as a strict comparison (===) will always return false as the variables don't contain the same object instance.

@malarzm malarzm modified the milestones: 2.5.3, 2.5.4 Oct 23, 2023
@malarzm malarzm modified the milestones: 2.5.4, 2.5.5 Nov 3, 2023
@alcaeus alcaeus removed this from the 2.5.5 milestone Nov 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants