Opened 4 years ago
Closed 4 years ago
#32256 closed Bug (fixed)
squashmigrations optimizer crashes when fields' names are swapped using a temporary name
Reported by: | InvalidInterrupt | Owned by: | Hasan Ramezani |
---|---|---|---|
Component: | Migrations | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | InvalidInterrupt | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If you rename fields using a pattern like a->c; b->a; c->b
(such as if previously DateTimeField
s using auto_now
and auto_now_add
had been mixed-up) and then attempt to squashmigrations
with an optimization barrier between the CreateModel
and RenameField
s, the migration optimizer will attempt to create a CreateModel
operation object with two fields using the same name and fail. I'll attach a migration file that triggers the failure.
I believe the root cause of this issue is that django.db.migrations.operations.fields.RenameField
allows itself to optimize through (i.e be moved to the right of, I may have gotten this terminology wrong) other RenameField
operations that reference old_name
.
Attachments (2)
Change History (13)
by , 4 years ago
Attachment: | 0001_initial.py added |
---|
comment:1 by , 4 years ago
I don't have time to write a patch and tests myself at the moment. I'll assign myself once that changes, unless someone else picks this up first.
comment:2 by , 4 years ago
Cc: | added |
---|
comment:3 by , 4 years ago
Summary: | squashmigrations may traceback when fields' names are swapped using a temporary name → squashmigrations optimizer crashes when fields' names are swapped using a temporary name |
---|---|
Triage Stage: | Unreviewed → Accepted |
Thanks for the report.
It's squashed to a single CreateModel()
operation when the initial migration doesn't contain migrations.RunPython()
, but crashes if it does:
Traceback (most recent call last): File "manage.py", line 22, in <module> main() File "manage.py", line 18, in main execute_from_command_line(sys.argv) File "/django/django/core/management/__init__.py", line 419, in execute_from_command_line utility.execute() File "/django/django/core/management/__init__.py", line 413, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/django/django/core/management/base.py", line 354, in run_from_argv self.execute(*args, **cmd_options) File "/django/django/core/management/base.py", line 398, in execute output = self.handle(*args, **options) File "/django/django/core/management/commands/squashmigrations.py", line 145, in handle new_operations = optimizer.optimize(operations, migration.app_label) File "/django/django/db/migrations/optimizer.py", line 34, in optimize result = self.optimize_inner(operations, app_label) File "/django/django/db/migrations/optimizer.py", line 47, in optimize_inner result = operation.reduce(other, app_label) File "/django/django/db/migrations/operations/models.py", line 233, in reduce CreateModel( File "/django/django/db/migrations/operations/models.py", line 55, in __init__ _check_for_duplicates('fields', (name for name, _ in self.fields)) File "/django/django/db/migrations/operations/models.py", line 17, in _check_for_duplicates raise ValueError( ValueError: Found duplicate value field_a in CreateModel fields argument.
comment:4 by , 4 years ago
I attached a sample project, manage.py squashmigrations test_one 0001 0004
reproduces this issue.
comment:6 by , 4 years ago
Patch needs improvement: | set |
---|
comment:7 by , 4 years ago
Comment from @InvalidInterrupt on PR:
Thanks to having your test as reference I put together my idea for fixing this in RenameField.reduce() here: https://github.com/InvalidInterrupt/django/tree/ticket_32256. I think it's better to fix this there rather than try to prevent the optimizer from considering such optimizations in the first case; other proposed features I've seen in trac (i.e. https://code.djangoproject.com/ticket/27844) would be likely to cause the issue to arise again. My approach does imply that this sequence of migrations is not optimizable; I would be happy to be proven wrong if someone identified a way to optimize this in the general case. I'm (probably overly) concerned about stepping on toes here, so I'm not making another PR. I may find myself busy again over the next couple days; please feel free to either ask me to make a PR or just take my commit if that's easier for you all.
I am not sure about the solution proposed by @InvalidInterrupt.
@Mariusz Could you please clarify it? If you agree with the proposed solution I can update the PR with the proposed solution.
Thanks
comment:8 by , 4 years ago
Patch needs improvement: | unset |
---|
comment:9 by , 4 years ago
Patch needs improvement: | set |
---|
I am not sure about the solution proposed by @InvalidInterrupt.
Sounds reasonable.
comment:10 by , 4 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
example migration