[Django] #34304: Adding and removing a conditional UniqueConstraint to ForeignKey multiple times crashes on MySQL

47 views
Skip to first unread message

Django

unread,
Jan 30, 2023, 11:36:02 AM1/30/23
to django-...@googlegroups.com
#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.

Django

unread,
Jan 30, 2023, 11:40:39 AM1/30/23
to django-...@googlegroups.com
#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 | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Description changed by Sage Abdullah:

Old description:

New description:

Test in `tests.schema.tests`:

{{{

This issue only happens on MySQL, even 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.)

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:1>

Django

unread,
Jan 30, 2023, 11:41:07 AM1/30/23
to django-...@googlegroups.com

Old description:

> triggering the error. This issue only happens on MySQL, even

New description:

Test in `tests.schema.tests`:

{{{

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

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:2>

Django

unread,
Jan 30, 2023, 11:51:20 AM1/30/23
to django-...@googlegroups.com
#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 | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-----------------------------------------
Changes (by Sage Abdullah):

* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/16509 PR].

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:3>

Django

unread,
Jan 30, 2023, 11:52:24 AM1/30/23
to django-...@googlegroups.com
#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: Database layer | Version: 4.2
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: GeyseR | Triage Stage: Accepted

Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* cc: mysql (added)
* keywords: => GeyseR
* component: Migrations => Database layer (models, ORM)
* severity: Normal => Release blocker
* stage: Unreviewed => Accepted


Comment:

Thanks for the report.

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:4>

Django

unread,
Jan 31, 2023, 5:52:58 AM1/31/23
to django-...@googlegroups.com
#34304: Adding and removing a conditional UniqueConstraint to ForeignKey multiple
times crashes on MySQL
-------------------------------------+-------------------------------------
Reporter: Sage Abdullah | Owner: Sage
| Abdullah
Type: Bug | Status: closed

Component: Database layer | Version: 4.2
(models, ORM) |
Severity: Release blocker | Resolution: fixed

Keywords: GeyseR | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by GitHub <noreply@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"110b3b83567da22f19ec04210db134d0fe83d662" 110b3b83]:
{{{
#!CommitTicketReference repository=""
revision="110b3b83567da22f19ec04210db134d0fe83d662"
Fixed #34304 -- Made MySQL's SchemaEditor.remove_constraint() don't create
foreign key index when unique constraint is ignored.

Regression in b731e8841558ee4caaba766c83f34ea9c7004f8b.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:5>

Django

unread,
Jan 31, 2023, 5:53:47 AM1/31/23
to django-...@googlegroups.com
#34304: Adding and removing a conditional UniqueConstraint to ForeignKey multiple
times crashes on MySQL
-------------------------------------+-------------------------------------
Reporter: Sage Abdullah | Owner: Sage
| Abdullah
Type: Bug | Status: closed
Component: Database layer | Version: 4.2
(models, ORM) |
Severity: Release blocker | Resolution: fixed
Keywords: GeyseR | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Mariusz Felisiak <felisiak.mariusz@…>):

In [changeset:"5e0be0873ca6fe0c4ad7abe1398443bdf367d16e" 5e0be087]:
{{{
#!CommitTicketReference repository=""
revision="5e0be0873ca6fe0c4ad7abe1398443bdf367d16e"
[4.2.x] Fixed #34304 -- Made MySQL's SchemaEditor.remove_constraint()


don't create foreign key index when unique constraint is ignored.

Regression in b731e8841558ee4caaba766c83f34ea9c7004f8b.
Backport of 110b3b83567da22f19ec04210db134d0fe83d662 from main
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/34304#comment:6>

Reply all
Reply to author
Forward
0 new messages