Skip to content

Renaming superclass causes migrations to produce invalid SQL #396

@marnanel

Description

@marnanel

Renaming a superclass causes "manage.py migrate" to produce invalid SQL. It attempts to copy zero columns from the old model to the updated model.

Tested using cpython 3.6.7 and django_polymorphic 2.0.3.

Demonstration, with the attached file
polybug.tar.gz:

Migrations for 'bugdemo':
  bugdemo/migrations/0001_initial.py
    - Create model Rodent
    - Create model Capybara
    - Create model Rat
$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, bugdemo, contenttypes, sessions
Running migrations:
[...]
  Applying bugdemo.0001_initial... OK
  Applying sessions.0001_initial... OK
$

[here, rename Rodent to CuddlyRodent throughout models.py]

You are trying to add a non-nullable field 'cuddlyrodent_ptr' to capybara without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 0
You are trying to add a non-nullable field 'cuddlyrodent_ptr' to rat without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 0
Migrations for 'bugdemo':
  bugdemo/migrations/0002_auto_20190805_1354.py
    - Create model CuddlyRodent
    - Remove field rodent_ptr from capybara
    - Remove field rodent_ptr from rat
    - Delete model Rodent
    - Add field cuddlyrodent_ptr to capybara
    - Add field cuddlyrodent_ptr to rat
$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, bugdemo, contenttypes, sessions
Running migrations:
  Applying bugdemo.0002_auto_20190805_1354...Traceback (most recent call last):
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params) 
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 383, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: near ")": syntax error

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_co
mmand_line
    utility.execute()
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)  
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 234, in handle
    fake_initial=fake_initial,
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/migrations/operations/fields.py", line 178, in database_forwards
    schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/sqlite3/schema.py", line 345, in remove_field
    self._remake_table(model, delete_field=field)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/sqlite3/schema.py", line 286, in _remake_table
    self.quote_name(model._meta.db_table),
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 137, in execute
    cursor.execute(sql, params)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 99, in execute
    return super().execute(sql, params)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 383, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: near ")": syntax error

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions