Opened 10 years ago

Closed 10 years ago

Last modified 9 years ago

#24972 closed Bug (fixed)

Removing unique_together constraint makes migration fail on Django 1.8.2 with MySQL

Reported by: Adam Brenecki Owned by: Adam Brenecki
Component: Migrations Version: 1.9
Severity: Release blocker Keywords:
Cc: 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

Migrations containing migrations.AlterUniqueTogether(name='xxx', unique_together=set([]),) may fail on Django 1.8 but not on Django 1.7 if using the backend mysql, but in a slightly different way than in #24757.

Given the following models:

from django.db import models

# Create your models here.
class FkTarget(models.Model):
    pass

class TheModel(models.Model):
    fk = models.ForeignKey(FkTarget)
    other = models.IntegerField()

And the following migrations:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='FkTarget',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ],
        ),
        migrations.CreateModel(
            name='TheModel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('other', models.IntegerField()),
            ],
        ),
        migrations.AddField(
            model_name='themodel',
            name='fk',
            field=models.ForeignKey(default=1, to='ta.FkTarget'),
            preserve_default=False,
        ),
        migrations.AlterUniqueTogether(
            name='themodel',
            unique_together=set([('fk', 'other')]),
        ),
    ]  
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('ta', '0001_initial'),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name='themodel',
            unique_together=set([]),
        ),
    ]

I get the following error when migrating:

  Applying ta.0001_initial... OK
  Applying ta.0002_auto_20150612_0354...Traceback (most recent call last):
  
    [snip traceback]
    
django.db.utils.OperationalError: (1061, "Duplicate key name 'ta_themodel_4195ef88'")

What seems to be happening here is that the AddField is doing a CREATE INDEX on the fk field, then the final AlterUniqueTogether is trying to recreate the already-existing index.

(Interestingly, if the foreign key is introduced as part of the CreateModel rather than as an AddField - which is how it was in #24757 - I don't see the first CREATE INDEX in sqlmigrate, and the whole thing works without errors.)

I think I've managed to figure out what's causing it and fix the issue; I'll post my patch up to GitHub shortly.

In case it's relevant:

$ mysqld --version
150612 13:42:17 [Warning] Using unique option prefix key_buffer instead of key_buffer_size is deprecated and will be removed in a future release. Please use the full name instead.
mysqld  Ver 5.5.43-0ubuntu0.14.04.1-log for debian-linux-gnu on x86_64 ((Ubuntu))

Change History (11)

comment:1 by Adam Brenecki, 10 years ago

Owner: changed from nobody to Adam Brenecki
Status: newassigned

So I have a patch for this, I just haven't written a regression test yet.

Version 0, edited 10 years ago by Adam Brenecki (next)

comment:2 by Shai Berger, 10 years ago

#24934 seems to describe the same problem and was marked as fixed. Can you please check against master?

in reply to:  2 comment:3 by Adam Brenecki, 10 years ago

Replying to shaib:

#24934 seems to describe the same problem and was marked as fixed. Can you please check against master?

Same problem on master for me.

comment:4 by Tim Graham, 10 years ago

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

comment:5 by Adam Brenecki, 10 years ago

Has patch: set

OK, patch is here: https://github.com/django/django/pull/4859

Sorry it took so long; I had issues with djangocore-box on Friday and didn't have time over the weekend :(

comment:6 by Tim Graham, 10 years ago

Triage Stage: AcceptedReady for checkin

Made some minor edits and now running tests locally just to double check.

comment:7 by Tim Graham <timograham@…>, 10 years ago

Resolution: fixed
Status: assignedclosed

In 65296b3:

Fixed #24972 -- Fixed removing unique_together indexes on MySQL.

comment:8 by Tim Graham <timograham@…>, 10 years ago

In 0e3a80f:

[1.8.x] Fixed #24972 -- Fixed removing unique_together indexes on MySQL.

Backport of 65296b3be376e9cd25216b6ad2b1758b03765781 from master

comment:9 by Adam Nelson, 9 years ago

Version: 1.81.9

This still seems to be a problem.

MySQL 5.6
Django 1.9.4
Python 3.5

In this case I'm dropping a unique_with constraint on a table called "stream_streamaccess"

class Migration(migrations.Migration):

    dependencies = [
        ('stream', '0002_auto_20160406_1501'),
    ]

    operations = [
        migrations.AlterUniqueTogether(
            name='streamaccess',
            unique_together=set([]),
        ),
    ]

Running migrations:
  Rendering model states... DONE
  Applying stream.0003_auto_20160406_2130...Traceback (most recent call last):
  File "/var/www/centr/manage.py", line 13, in <module>
    execute_from_command_line(sys.argv)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
    utility.execute()
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/core/management/__init__.py", line 345, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/core/management/base.py", line 348, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/core/management/base.py", line 399, in execute
    output = self.handle(*args, **options)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 200, in handle
    executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
  File "/var/virtualenvs/centr/lib/python3.5/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 "/var/virtualenvs/centr/lib/python3.5/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 "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/migrations/migration.py", line 123, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/migrations/operations/models.py", line 359, in database_forwards
    getattr(new_model._meta, self.option_name, set()),
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 318, in alter_unique_together
    self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/backends/mysql/schema.py", line 87, in _delete_composed_index
    return super(DatabaseSchemaEditor, self)._delete_composed_index(model, fields, *args)
  File "/var/virtualenvs/centr/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 347, in _delete_composed_index
    ", ".join(columns),
ValueError: Found wrong number (0) of constraints for stream_streamaccess(stream_id, user_id, role)

comment:10 by Tim Graham, 9 years ago

Please open a new ticket with steps to reproduce (such as a sample project).

comment:11 by Adam Nelson, 9 years ago

I just tried replicating and couldn't get it to happen again. Unfortunately I fried all of my previous migrations to get it to work on the real project and my test project starting from scratch worked fine. I guess we'll leave well enough alone.

Note: See TracTickets for help on using tickets.
Back to Top