#34304: Adding and removing a conditional UniqueConstraint to ForeignKey 
multiple
times crashes on MySQL
-----------------------------------------+-------------------------------
               Reporter:  Sage Abdullah  |          Owner:  Sage Abdullah
                   Type:  Bug            |         Status:  assigned
              Component:  Migrations     |        Version:  4.2
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+-------------------------------
 Adding and removing a `UniqueConstraint` to `ForeignKey` with a
 `condition` more than once on MySQL will crash the schema editor an
 `OperationalError`, e.g. `django.db.utils.OperationalError: (1061,
 "Duplicate key name 'schema_book_author_id_c80c8297'")`

 Test in `tests.schema.tests`:

 {{{


     def test_unique_with_fk_and_condition_multiple_times(self):
         """
         Tests adding and removing a unique constraint to ForeignKey
         with a condition multiple times.
         """
         with connection.schema_editor() as editor:
             editor.create_model(Author)
             editor.create_model(Book)
         constraint = UniqueConstraint(
             "author",
             condition=Q(title__in=["tHGttG", "tRatEotU"]),
             name="book_author_condition_uniq",
         )

         for i in range(2):
             # Add constraint.
             with connection.schema_editor() as editor:
                 editor.add_constraint(Book, constraint)
                 sql = constraint.create_sql(Book, editor)
             book_table = Book._meta.db_table
             constraints = self.get_constraints(book_table)
             if connection.features.supports_partial_indexes:
                 self.assertIn(constraint.name, constraints)
                 self.assertIs(constraints[constraint.name]["unique"],
 True)
                 self.assertIn("WHERE %s IN" % editor.quote_name("title"),
 str(sql))
             else:
                 self.assertNotIn(constraint.name, constraints)
                 self.assertIsNone(sql)
             # Remove constraint.
             with connection.schema_editor() as editor:
                 editor.remove_constraint(Book, constraint)
             self.assertNotIn(constraint.name,
 self.get_constraints(book_table))
 }}}

 This is a regression in b731e8841558ee4caaba766c83f34ea9c7004f8b.

 Use case:
 [https://github.com/wagtail/wagtail Wagtail] supports multiple database
 backends. We have a migration that adds a unique constraint to a foreign
 key with a condition. In addition, we also have migrations that alter the
 field referenced in the condition. Before making an alter field operation,
 we need to remove the unique constraint to avoid violating the constraint,
 then re-add the constraint after the field has been altered. We have more
 than one migrations that do these operations, thus triggering the error.
 This issue only happens on MySQL, specifically after the above commit was
 merged into Django.

 Relevant migrations in Wagtail:
 -
 
[https://github.com/wagtail/wagtail/blob/main/wagtail/migrations/0050_workflow_rejected_to_needs_changes.py
 0050_workflow_rejected_to_needs_changes]: First instance of
 `RemoveConstraint` and `AddConstraint`
 -
 
[https://github.com/wagtail/wagtail/blob/main/wagtail/migrations/0060_fix_workflow_unique_constraint.py
 0060_fix_workflow_unique_constraint]: another instance, this fails to run.
 (Though, I know this migration doesn't really do anything.)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34304>
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/01070186038908cd-8221ddfc-0df2-44bc-b8a9-6ce142eec2e1-000000%40eu-central-1.amazonses.com.

Reply via email to