Commit c56c42b5 authored by Jozef Knaperek's avatar Jozef Knaperek Committed by Anssi Kääriäinen
Browse files

Fixed #22967 -- Made Model._do_update consistent

Made _do_update behave more strictly according to its docs,
including a corner case when specific concurent updates are
executed and select_on_save is set.
parent d647764a
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -757,8 +757,14 @@ class Model(six.with_metaclass(ModelBase)):
            return update_fields is not None or filtered.exists()
        if self._meta.select_on_save and not forced_update:
            if filtered.exists():
                filtered._update(values)
                return True
                # It may happen that the object is deleted from the DB right after
                # this check, causing the subsequent UPDATE to return zero matching
                # rows. The same result can occur in some rare cases when the
                # database returns zero despite the UPDATE being executed
                # successfully (a row is matched and updated). In order to
                # distinguish these two cases, the object's existence in the
                # database is again checked for if the UPDATE query returns 0.
                return filtered._update(values) > 0 or filtered.exists()
            else:
                return False
        return filtered._update(values) > 0
+1 −1
Original line number Diff line number Diff line
@@ -701,7 +701,7 @@ class SelectOnSaveTests(TestCase):
        try:
            Article._base_manager.__class__ = FakeManager
            asos = ArticleSelectOnSave.objects.create(pub_date=datetime.now())
            with self.assertNumQueries(2):
            with self.assertNumQueries(3):
                asos.save()
                self.assertTrue(FakeQuerySet.called)
            # This is not wanted behavior, but this is how Django has always