django-polymorphic icon indicating copy to clipboard operation
django-polymorphic copied to clipboard

Renaming superclass causes migrations to produce invalid SQL

Open marnanel opened this issue 6 years ago • 3 comments

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

marnanel avatar Aug 05 '19 14:08 marnanel

Still present in version polymorphic v.3.0.0, Django v.3.2.5, python 3.9

StevenMonty avatar Aug 05 '21 20:08 StevenMonty

Same problem with v3.1.0 and Django 3.2.16

Alegege avatar Nov 09 '22 16:11 Alegege