#27746: Database migration fail when removing a child model containing only
foreignkeys in a multi-table inheritance context on MySQL
-------------------------------------+-------------------------------------
Reporter: David | Owner: nobody
CHANIAL |
Type: Bug | Status: new
Component: Database | Version: 1.9
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
== Context
* I'm not observing this bug when not using '''multi-table inheritance'''.
* I'm using '''MySQL''' (''MariaDB-10.0''), and i don't know if the bug
happen with another database backend or server.
* In an existing project named '''bobb'''
* A similary bug exist with empty child models too, like '''Account''' or
'''Device'''
== Prepare the bug
{{{
python manage.py startapp buggymigration
echo "INSTALLED_APPS = tuple(list(INSTALLED_APPS) + ['buggymigration'])"
>> bobb/settings.py
# creating models using multi-table in heritance in buggymigration
# by making changes to buggymigration/models.py
cat buggymigration/models.py
}}}
{{{
#!python
from __future__ import unicode_literals
from django.db import models
class UniqueSerialNumber(models.Model):
pass
class Account(UniqueSerialNumber):
pass
class Device(UniqueSerialNumber):
pass
class Contract(UniqueSerialNumber):
customer = models.ForeignKey('Account')
machine = models.ForeignKey('Device')
}}}
{{{
python manage.py makemigrations
}}}
{{{
Migrations for 'buggymigration':
0001_initial.py:
- Create model UniqueSerialNumber
- Create model Account
- Create model Contract
- Create model Device
- Add field machine to contract
}}}
{{{
python manage.py migrate
}}}
{{{
Operations to perform:
Apply all migrations: sessions, admin, auth, buggymigration,
contenttypes
Running migrations:
Applying buggymigration.0001_initial... OK
}}}
== Trigger the bug
{{{
# trying to remove the model Contract
# by editing buggymigration/models.py and commenting the model
cat buggymigration/models.py
}}}
{{{
#!python
from __future__ import unicode_literals
from django.db import models
class UniqueSerialNumber(models.Model):
pass
class Account(UniqueSerialNumber):
pass
class Device(UniqueSerialNumber):
pass
'''
class Contract(UniqueSerialNumber):
customer = models.ForeignKey('Account')
machine = models.ForeignKey('Device')
'''
}}}
{{{
python manage.py makemigrations
}}}
{{{
Migrations for 'buggymigration':
0002_auto_20170118_1258.py:
- Remove field customer from contract
- Remove field machine from contract
- Remove field uniqueserialnumber_ptr from contract
- Delete model Contract
}}}
{{{
cat buggymigration/migrations/0002_auto_20170118_1258.py
}}}
{{{
#!python
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-01-18 11:58
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('buggymigration', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='contract',
name='customer',
),
migrations.RemoveField(
model_name='contract',
name='machine',
),
migrations.RemoveField(
model_name='contract',
name='uniqueserialnumber_ptr',
),
migrations.DeleteModel(
name='Contract',
),
]
}}}
{{{
python manage.py sqlmigrate buggymigration 0002_auto_20170118_1258
}}}
{{{
#!sql
BEGIN;
--
-- Remove field customer from contract
--
ALTER TABLE `buggymigration_contract` DROP FOREIGN KEY
`D5e39daefe3dcc06188b9ecc2ad1e28a`;
ALTER TABLE `buggymigration_contract` DROP COLUMN `customer_id` CASCADE;
--
-- Remove field machine from contract
--
ALTER TABLE `buggymigration_contract` DROP FOREIGN KEY
`a46c0a1038d68a3574efaf2d757512fd`;
ALTER TABLE `buggymigration_contract` DROP COLUMN `machine_id` CASCADE;
--
-- Remove field uniqueserialnumber_ptr from contract
--
ALTER TABLE `buggymigration_contract` DROP FOREIGN KEY
`f406fa7acbef3134feeae510d6e9affd`;
ALTER TABLE `buggymigration_contract` DROP COLUMN
`uniqueserialnumber_ptr_id` CASCADE;
--
-- Delete model Contract
--
DROP TABLE `buggymigration_contract` CASCADE;
COMMIT;
}}}
== The bug
{{{
python manage.py migrate buggymigration
}}}
{{{
Operations to perform:
Apply all migrations: buggymigration
Running migrations:
Applying buggymigration.0002_auto_20170118_1258...Traceback (most recent
call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 353, in
execute_from_command_line
utility.execute()
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/core/management/commands/migrate.py", line 200, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 92, in migrate
self._migrate_all_forwards(plan, full_plan, fake=fake,
fake_initial=fake_initial)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 121, in
_migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake,
fake_initial=fake_initial)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 198, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/migrations/migration.py", line 123, in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/migrations/operations/fields.py", line 121, in
database_forwards
schema_editor.remove_field(from_model,
from_model._meta.get_field(self.name))
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/base/schema.py", line 438, in remove_field
self.execute(sql)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/base/schema.py", line 110, in execute
cursor.execute(sql, params)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/django/db/backends/mysql/base.py", line 112, in execute
return self.cursor.execute(query, args)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File "/home/backoffice/virtualenv/local/lib/python2.7/site-
packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
django.db.utils.OperationalError: (1090, "You can't delete all columns
with ALTER TABLE; use DROP TABLE instead")
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/27746>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.4efecd2e277cdfcb05306f9f0723a0ac%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.