Submit Blog  RSS Feeds

Thursday, May 10, 2012

Droping a multi-column unique constraint in MySQL with Django South

South is a great tool for managing database migrations (compatible with Django). It generates migrations by analysing the difference between the current data model and the previous one (stored in migration script files). However strange things may occur if you try do drop a multi-column unique constraint ( the django model defines it as: unique_together).  For example we have:


  1 class MyModel(models.Model):
  2     classs Meta:     
  3         app_label = 'myapp'
  4         unique_together = (('field1', 'field2',),)

We remove line 4, and run schemamigration:

~ ./manage.py schemamigration myapp --auto

South generates the following forward migration:

 23 class Migration(SchemaMigration):
 24     def forwards(self, orm):
 25         db.delete_unique('myapp_mymodel', ['field1', 'field2']) 

Let's try to execute it:

~ ./manage migrate kantor

And we get something like this:

ValueError: Cannot find a UNIQUE constraint on table myapp_mymodel, columns ['field1', 'field2']

We can investigate it using the mysql client:

mysql> SHOW CREATE TABLE myapp_mymodel;
(...)
UNIQUE KEY `myapp_mymodel_field1_667dc28f4f7b310_uniq` (`field1`,`field2`),
(...)

So the unique constraint really exists, but south fails to drop it. To solve this problem we have to drop that index ourselves. We should modify the forward migration the following way:

 23 class Migration(SchemaMigration):
 24     def forwards(self, orm):

 25         import south

 26         south.db.db.execute('drop index \
 27             myapp_mymodel_field1_667dc28f4f7b310_uniq on myapp_mymodel;')


That does the trick! Farewell multi-column unique constraints! 

~KR

2 comments:

free counters