Skip to content

Commit ed7898e

Browse files
charettestimgraham
authored andcommitted
Fixed #28862 -- Disabled optimization of AlterFooTogether and RemoveField.
AlterFooTogether operations cannot be swapped with RemoveField operations on the same model as they could be removing the the same field as well. Since AlterFooTogether operations don't track what their previous value was, it's impossible to determine whether or not the optimization is safe so the only way to proceed is to disable the optimization. Thanks Ramiro Morales for the in-depth analysis of the issue. Refs #24828
1 parent 55b6f7a commit ed7898e

File tree

4 files changed

+11
-17
lines changed

4 files changed

+11
-17
lines changed

django/db/migrations/operations/models.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -449,10 +449,11 @@ def reduce(self, operation, app_label=None):
449449

450450
class FieldRelatedOptionOperation(ModelOptionOperation):
451451
def reduce(self, operation, app_label=None):
452-
if (isinstance(operation, FieldOperation) and
453-
self.name_lower == operation.model_name_lower and
454-
not self.references_field(operation.model_name, operation.name)):
455-
return [operation, self]
452+
if isinstance(operation, FieldOperation) and self.name_lower == operation.model_name_lower:
453+
if isinstance(operation, RemoveField):
454+
return False
455+
if not self.references_field(operation.model_name, operation.name):
456+
return [operation, self]
456457
return super().reduce(operation, app_label=app_label)
457458

458459

tests/migrations/test_autodetector.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,10 +1529,10 @@ def test_remove_field_and_foo_together(self):
15291529
)
15301530
# Right number/type of migrations?
15311531
self.assertNumberMigrations(changes, "otherapp", 1)
1532-
self.assertOperationTypes(changes, "otherapp", 0, ["RemoveField", "AlterUniqueTogether", "AlterIndexTogether"])
1533-
self.assertOperationAttributes(changes, "otherapp", 0, 0, model_name="book", name="newfield")
1534-
self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={("author", "title")})
1535-
self.assertOperationAttributes(changes, "otherapp", 0, 2, name="book", index_together={("author", "title")})
1532+
self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether", "RemoveField"])
1533+
self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("author", "title")})
1534+
self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together={("author", "title")})
1535+
self.assertOperationAttributes(changes, "otherapp", 0, 2, model_name="book", name="newfield")
15361536

15371537
def test_rename_field_and_foo_together(self):
15381538
"""

tests/migrations/test_commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1335,7 +1335,7 @@ def test_squashmigrations_optimizes(self):
13351335
out = io.StringIO()
13361336
with self.temporary_migration_module(module="migrations.test_migrations"):
13371337
call_command("squashmigrations", "migrations", "0002", interactive=False, verbosity=1, stdout=out)
1338-
self.assertIn("Optimized from 8 operations to 3 operations.", out.getvalue())
1338+
self.assertIn("Optimized from 8 operations to 4 operations.", out.getvalue())
13391339

13401340
def test_ticket_23799_squashmigrations_no_optimize(self):
13411341
"""

tests/migrations/test_optimizer.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ def _test_create_alter_foo_field(self, alter):
712712
],
713713
)
714714

715-
self.assertOptimizesTo(
715+
self.assertDoesNotOptimize(
716716
[
717717
migrations.CreateModel("Foo", [
718718
("a", models.IntegerField()),
@@ -722,13 +722,6 @@ def _test_create_alter_foo_field(self, alter):
722722
alter,
723723
migrations.RemoveField("Foo", "c"),
724724
],
725-
[
726-
migrations.CreateModel("Foo", [
727-
("a", models.IntegerField()),
728-
("b", models.IntegerField()),
729-
]),
730-
alter,
731-
],
732725
)
733726

734727
def test_create_alter_unique_field(self):

0 commit comments

Comments
 (0)