#31788: Models migration with change field foreign to many and deleting unique
together.
----------------------------+-----------------------------------------
     Reporter:  budzichd    |                    Owner:  David Wobrock
         Type:  Bug         |                   Status:  assigned
    Component:  Migrations  |                  Version:  3.0
     Severity:  Normal      |               Resolution:
     Keywords:              |             Triage Stage:  Accepted
    Has patch:  1           |      Needs documentation:  0
  Needs tests:  0           |  Patch needs improvement:  0
Easy pickings:  0           |                    UI/UX:  0
----------------------------+-----------------------------------------
Changes (by David Wobrock):

 * cc: David Wobrock (added)
 * owner:  nobody => David Wobrock
 * has_patch:  0 => 1
 * status:  new => assigned


Comment:

 Quite a funny bug actually in the autodetector and how we sort migration
 with respect to their dependencies.
 I can't exactly reproduce the described output, but something similar.

 Here is a little dive into the issue.

 When changing a field from FK to M2M, the autodetector goes within
 
`django.db.migrations.autodetector.MigrationAutodetector.generate_altered_fields`
 and creates a `RemoveField`+`AddField`, which is fine and works.
 But we also generate a `AlterUniqueTogether`...

 Since we call `generate_removed_altered_unique_together` before
 `generate_altered_fields`, one would expect it to work as expected.
 And at first, we have the right operation order: `[AlterUniqueTogether,
 RemoveField, AddField]`.

 However, when sorting the operations with respect to their dependencies,
 we trigger the dependency that `RemoveField` should be after
 `AlterUniqueTogether`.
 Even if this condition is already satisfied, the `stable_topological_sort`
 changes the order and returns `[AlterUniqueTogether, AddField,
 RemoveField]`. The dependency is still satisfied, but our Remove/Add
 became an Add/Remove, which cannot work.
 In `tests/utils_tests/test_topological_sort.py`
 {{{
     def test_preserve_satisfied_order(self):
         dependency_graph = {1: set(), 2: {1}, 3: set()}
         self.assertEqual(
             stable_topological_sort([1, 2, 3], dependency_graph),
             [1, 2, 3],
         )
 }}}
 return
 {{{
 ======================================================================
 FAIL: test_preserve_satisfied_order
 (utils_tests.test_topological_sort.TopologicalSortTests)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "/home/david/django/tests/utils_tests/test_topological_sort.py",
 line 29, in test_preserve_satisfied_order
     self.assertEqual(
 AssertionError: Lists differ: [1, 3, 2] != [1, 2, 3]

 First differing element 1:
 3
 2

 - [1, 3, 2]
 + [1, 2, 3]
 }}}
 on my env (and since we rely on sets, I suspect that's why I don't have
 the same result as described in the ticket. I think that's why Simon is
 seeing a `[AddField, AlterUniqueTogether, RemoveField]`, which also
 satisfies the dependencies).

 (on top of that, the autodetector then optimizes the operations, and the
 `AddField` followed by `RemoveField` cancel each other out, and we end up
 with a single `[AlterUniqueTogether]`).

 Two possible approaches to fix this:
 1. Making the `AddField` depend on `RemoveField`, so that we force their
 order
 2. Changing the topological sort, so that it preserves the input order as
 much as possible

 Since the second might imply a large set of changes, so I tried
 implementing the first one in this
 [https://github.com/django/django/pull/15738 PR].

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31788#comment:5>
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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018105b881e1-04663909-0f5e-46fa-b13b-10cbc5d7779c-000000%40eu-central-1.amazonses.com.

Reply via email to