#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.