﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34304	Adding and removing a conditional UniqueConstraint to ForeignKey multiple times crashes on MySQL	Sage Abdullah	Sage Abdullah	"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. Even though conditional indexes aren't supported on MySQL, I believe it should just be ignored (as with previous releases) instead of crashing the schema editor.

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.)"	Bug	closed	Database layer (models, ORM)	4.2	Release blocker	fixed	GeyseR	mysql	Accepted	1	0	0	0	0	0
