mirror of https://github.com/django/django.git
Fixed #27845 -- Allowed both right and left optimizations of operations.
Thanks Raphael Gaschignard for the suggestion.
This commit is contained in:
parent
0025dd5eb4
commit
37cafbfb79
|
@ -42,21 +42,29 @@ class MigrationOptimizer:
|
||||||
"""Inner optimization loop."""
|
"""Inner optimization loop."""
|
||||||
new_operations = []
|
new_operations = []
|
||||||
for i, operation in enumerate(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
|
# Compare it to each operation after it
|
||||||
for j, other in enumerate(operations[i + 1:]):
|
for j, other in enumerate(operations[i + 1:]):
|
||||||
in_between = operations[i + 1:i + j + 1]
|
in_between = operations[i + 1:i + j + 1]
|
||||||
result = operation.reduce(other, in_between, app_label)
|
result = operation.reduce(other, in_between, app_label)
|
||||||
if isinstance(result, list):
|
if isinstance(result, list):
|
||||||
# Add operations optimized through, optimized operations,
|
if right:
|
||||||
# and the remaining ones.
|
new_operations.extend(in_between)
|
||||||
new_operations.extend(in_between)
|
new_operations.extend(result)
|
||||||
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:])
|
new_operations.extend(operations[i + j + 2:])
|
||||||
return new_operations
|
return new_operations
|
||||||
if not result:
|
elif not result:
|
||||||
# We can't optimize across `other`.
|
# Can't perform a right reduction.
|
||||||
new_operations.append(operation)
|
right = False
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
new_operations.append(operation)
|
new_operations.append(operation)
|
||||||
return new_operations
|
return new_operations
|
||||||
|
|
|
@ -270,8 +270,6 @@ class OptimizerTests(SimpleTestCase):
|
||||||
app_label="testapp",
|
app_label="testapp",
|
||||||
)
|
)
|
||||||
|
|
||||||
# This could be optimized a bit more but it generates a valid set of
|
|
||||||
# operations.
|
|
||||||
self.assertOptimizesTo(
|
self.assertOptimizesTo(
|
||||||
[
|
[
|
||||||
migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]),
|
migrations.CreateModel('Book', [('name', models.CharField(max_length=255))]),
|
||||||
|
@ -284,18 +282,12 @@ class OptimizerTests(SimpleTestCase):
|
||||||
migrations.DeleteModel('Person'),
|
migrations.DeleteModel('Person'),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
migrations.CreateModel('Person', [('name', models.CharField(max_length=255))]),
|
migrations.CreateModel('Book', [('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('Reviewer', [('name', models.CharField(max_length=255))]),
|
migrations.CreateModel('Reviewer', [('name', models.CharField(max_length=255))]),
|
||||||
migrations.CreateModel('Review', [
|
migrations.CreateModel('Review', [
|
||||||
('book', models.ForeignKey('test_app.Book', models.CASCADE)),
|
('book', models.ForeignKey('test_app.Book', models.CASCADE)),
|
||||||
('reviewer', models.ForeignKey('test_app.Reviewer', models.CASCADE)),
|
('reviewer', models.ForeignKey('test_app.Reviewer', models.CASCADE)),
|
||||||
]),
|
]),
|
||||||
migrations.RemoveField('book', 'author'),
|
|
||||||
migrations.DeleteModel('Person'),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue