#30966: Migration crashes due to foreign key issue, depending on otherwise
irrelevant order on MySQL.
-------------------------------------+-------------------------------------
     Reporter:  Peter Thomassen      |                    Owner:  Hasan
                                     |  Ramezani
         Type:  Bug                  |                   Status:  assigned
    Component:  Migrations           |                  Version:  master
     Severity:  Normal               |               Resolution:
     Keywords:  migration mySQL      |             Triage Stage:  Accepted
    Has patch:  1                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  1
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Simon Charette):

 After doing a bit of investigation work for #31064 and revisiting #29000 I
 think the solution proposed by Hasan makes the most sense for now and
 here's why.

 Let's take the setup defined to test #29000 as an example

 {{{#!python
 class Pony(models.Model):
     name = models.CharField(max_length=20)

 class Rider(models.Model):
    pony = models.ForeignKey('test_rename_multiple.Pony', models.CASCADE)

 class PonyRider(models.Model):
    riders = models.ManyToManyField('Rider')
 }}}

 If a `RenameField('Pony', 'name', 'fancy_field)` operation is applied and
 `Pony` is rendered from the new state only the `Rider.pony` pointer is
 actually stale and needs to be repointed.

 However we decided not to follow the repointing route because of all the
 trouble it incurs. Instead we re-render only the direct relationships if
 `delay=True` (only `Rider` in this case) or the full relationship tree if
 `delay=False` (`Rider` and `PonyRider` in this case). A full relationship
 tree re-rendering is slow hence why we try to use `delay=True` as much as
 possible but when we do so references to direct relationships of the
 reloaded models are left pointing at pre-re-rendering `Model` classes
 which breaks `Options._populate_directed_relation_graph` mapping because
 it currently relies on `Options` identity as key.

 To reuse our example setup above, if `PonyRider -> Rider -> Pony` and we
 `reload_model('app', 'pony', delay=True)` then `Pony` and `Rider` will be
 reloaded as `Rider' -> Pony'` but `PonyRider` will still point at `Pony`
 and not `Pony'` which makes any following operation relying on
 `Pony'._meta.related_objects` break because `Pony'._meta is not
 Pony._meta`.

 If we look at how #29000 was addressed
 
[https://github.com/django/django/commit/fcc4e251dbc917118f73d7187ee2f4cbf3883f36
 #diff-efb7d00c2383393046c9c5d842f45499R290 we can see that it works around
 this issue by forcing a full relationship tree re-rendering as soon as any
 model refers to a model on which a field is renamed]. This is really
 wasteful but it gets the test passing in this particular case which is
 more a bandaid than anything else. Fundamentally the `delay=True` model if
 broken if it doesn't allow non-re-rendered models to maintain some
 relationship with the re-rendered graph.

 For these reasons and because model identity consistency is not necessary
 beyond direct relationship by the current schema editor I think that
 adjusting `Options._populate_directed_relation_graph` to use
 `Options.label` as relationship key is our best way forward here as it
 doesn't hurt non-`__fake__` model relationship resolution and it allows
 `StateApps` to keep relying on the `delay=True` for model rendering until
 schema alterations don't necessitate access to `ProjectState.apps`
 anymore.

 I'll submit a PR that reverts unnecessary `RenameField.state_forwards`
 changes introduced by fcc4e251dbc917118f73d7187ee2f4cbf3883f36 and use
 Hasan's `_populate_directed_relation_graph` adjustments to demonstrate
 that the tests are passing. From that point, if everyone agrees that this
 is the right way forward, I think we should keep this ticket opened as a
 marker to add regression tests showing this is was properly addressed.

 Thoughts on that approach Markus and Hasan?

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30966#comment:21>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/072.b34def39e4405d07706615cca19a12e9%40djangoproject.com.

Reply via email to