﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
27746	Database migration fail when removing a child model containing only foreignkeys in a multi-table inheritance context on MySQL	David CHANIAL	nobody	"== 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"")
}}}
"	Bug	new	Migrations	dev	Normal				Accepted	0	0	0	0	0	0
