From 37cafbfb791b2295b8c36cdabbdef0e5d951a64e Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Sat, 18 Feb 2017 00:55:13 -0500 Subject: [PATCH] Fixed #27845 -- Allowed both right and left optimizations of operations. Thanks Raphael Gaschignard for the suggestion. --- django/db/migrations/optimizer.py | 24 ++++++++++++++++-------- tests/migrations/test_optimizer.py | 10 +--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/django/db/migrations/optimizer.py b/django/db/migrations/optimizer.py index 26ac88a221..7974dba66b 100644 --- a/django/db/migrations/optimizer.py +++ b/django/db/migrations/optimizer.py @@ -42,21 +42,29 @@ class MigrationOptimizer: """Inner optimization loop.""" new_operations = [] for i, operation in enumerate(operations): + right = True # Should we reduce on the right or on the left. # Compare it to each operation after it for j, other in enumerate(operations[i + 1:]): in_between = operations[i + 1:i + j + 1] result = operation.reduce(other, in_between, app_label) if isinstance(result, list): - # Add operations optimized through, optimized operations, - # and the remaining ones. - new_operations.extend(in_between) - new_operations.extend(result) + if right: + new_operations.extend(in_between) + new_operations.extend(result) + elif all(op.reduce(other, [], app_label) is True for op in in_between): + # Perform a left reduction if all of the in-between + # operations can optimize through other. + new_operations.extend(result) + new_operations.extend(in_between) + else: + # Otherwise keep trying. + new_operations.append(operation) + break new_operations.extend(operations[i + j + 2:]) return new_operations - if not result: - # We can't optimize across `other`. - new_operations.append(operation) - break + elif not result: + # Can't perform a right reduction. + right = False else: new_operations.append(operation) return new_operations diff --git a/tests/migrations/test_optimizer.py b/tests/migrations/test_optimizer.py index 973be67c80..a408db9ef2 100644 --- a/tests/migrations/test_optimizer.py +++ b/tests/migrations/test_optimizer.py @@ -270,8 +270,6 @@ class OptimizerTests(SimpleTestCase): app_label="testapp", ) - # This could be optimized a bit more but it generates a valid set of - # operations. self.assertOptimizesTo( [ migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]), @@ -284,18 +282,12 @@ class OptimizerTests(SimpleTestCase): migrations.DeleteModel('Person'), ], [ - migrations.CreateModel('Person', [('name', models.CharField(max_length=255))]), - migrations.CreateModel('Book', [ - ('name', models.CharField(max_length=255)), - ('author', models.ForeignKey('test_app.Person', models.CASCADE)), - ]), + migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]), migrations.CreateModel('Reviewer', [('name', models.CharField(max_length=255))]), migrations.CreateModel('Review', [ ('book', models.ForeignKey('test_app.Book', models.CASCADE)), ('reviewer', models.ForeignKey('test_app.Reviewer', models.CASCADE)), ]), - migrations.RemoveField('book', 'author'), - migrations.DeleteModel('Person'), ], )