My team and I have encountered a problem in migrations when changing
relationship between models from OneToOneField to ForeignKey.
Original thread on django-users can be found here:
https://groups.google.com/forum/?#!topic/django-users/-NUbqzS4jQs
== Environment ==
* OS: Unix (Ubuntu 14.04)/OSX
* Django: 1.7.3
* DB: MySQL 5.6.22
== Steps to reproduce ==
1. Create two models:
{{{
class Model_A(models.Model):
id_A = models.AutoField(primary_key=True)
class Model_B(models.Model):
model_a = models.OneToOneField(Model_A)
}}}
2. Make migrations and perform migration. So far everything is OK.
3. Now change OneToOneField to ForeignKey:
{{{
class Model_A(models.Model):
id_A = models.AutoField(primary_key=True)
class Model_B(models.Model):
model_a = models.ForeignKey(Model_A)
}}}
4. Run migrations (makemigrations) and apply changes to db (migrate). We
get this error:
we get an error:
{{{
Cannot drop index 'model_a_id': needed in a foreign key constraint
}}}
It seems that Django tries to run SQL commands in following order:
{{{
ALTER TABLE 'xxx' DROP INDEX 'yyy' and
ALTER TABLE `xxx` DROP FOREIGN KEY `xxx_yyy_id_{some_hash}_fk_yyy_id`;
}}}
but if above commands are run in reverse order:
{{{
ALTER TABLE `xxx` DROP FOREIGN KEY `xxx_yyy_id_{some_hash}_fk_yyy_id`;
ALTER TABLE 'xxx' DROP INDEX 'yyy' and
}}}
everything is OK.
I have created sample project where it can be reproduced (last three
commits are reproducing above steps): https://github.com/harnash/django-
migration-bug/commits/master
--
Ticket URL: <https://code.djangoproject.com/ticket/24163>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: MarkusH (added)
* needs_better_patch: => 0
* needs_docs: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted
Comment:
Problem only occurs on MySQL (didn't test Oracle though)
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:1>
* owner: nobody => MarkusH
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:2>
* has_patch: 0 => 1
Comment:
PR: https://github.com/django/django/pull/3951
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:3>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:4>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"5792e6a88c1444d4ec84abe62077338ad3765b80"]:
{{{
#!CommitTicketReference repository=""
revision="5792e6a88c1444d4ec84abe62077338ad3765b80"
Fixed #24163 -- Removed unique constraint after index on MySQL
Thanks Łukasz Harasimowicz for the report.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:5>
Comment (by Markus Holtermann <info@…>):
In [changeset:"e55cb91bd47d054d502c03cdbe74ac98986af3fb"]:
{{{
#!CommitTicketReference repository=""
revision="e55cb91bd47d054d502c03cdbe74ac98986af3fb"
[1.8.x] Fixed #24163 -- Removed unique constraint after index on MySQL
Thanks Łukasz Harasimowicz for the report.
Backport of 5792e6a88c1444d4ec84abe62077338ad3765b80 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:6>
Comment (by Markus Holtermann <info@…>):
In [changeset:"db2a97870d74bc689428d9c2a942115ef799f2d2"]:
{{{
#!CommitTicketReference repository=""
revision="db2a97870d74bc689428d9c2a942115ef799f2d2"
[1.7.x] Fixed #24163 -- Removed unique constraint after index on MySQL
Thanks Łukasz Harasimowicz for the report.
Backport of 5792e6a88c1444d4ec84abe62077338ad3765b80 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:7>
* status: closed => new
* has_patch: 1 => 0
* resolution: fixed =>
* stage: Ready for checkin => Accepted
Comment:
The recent change breaks tests on Oracle:
http://djangoci.com/job/django-
oracle/lastCompletedBuild/database=oracle11,python=python3.4/testReport/schema.tests/SchemaTests/test_alter_fk_to_o2o/
{{{#!python
======================================================================
FAIL [0.001s]: test_alter_fk_to_o2o (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jenkins/workspace/django-
oracle/database/oracle11/python/python3.4/tests/schema/tests.py", line
629, in test_alter_fk_to_o2o
self.assertTrue(author_is_unique, "No unique constraint for author_id
found")
AssertionError: False is not true : No unique constraint for author_id
found
----------------------------------------------------------------------
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:8>
* has_patch: 0 => 1
Comment:
PR with Oracle fix: https://github.com/django/django/pull/3960
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:9>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:10>
Comment (by Markus Holtermann <info@…>):
In [changeset:"64ecb3f07db4be5eef4d9eb7687f783ee446c82f"]:
{{{
#!CommitTicketReference repository=""
revision="64ecb3f07db4be5eef4d9eb7687f783ee446c82f"
Refs #24163 -- Fixed failing Oracle test when migrating from ForeignKey to
OneToOneField
Thanks Tim Graham for review
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:11>
Comment (by Markus Holtermann <info@…>):
In [changeset:"20f1aafa14798d8caac74319a335668ffe86c224"]:
{{{
#!CommitTicketReference repository=""
revision="20f1aafa14798d8caac74319a335668ffe86c224"
[1.8.x] Refs #24163 -- Fixed failing Oracle test when migrating from
ForeignKey to OneToOneField
Thanks Tim Graham for review
Backport of 64ecb3f07db4be5eef4d9eb7687f783ee446c82f from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:12>
Comment (by Markus Holtermann <info@…>):
In [changeset:"70845c6809f53d9d4029d760aa0118a47b92cb9d"]:
{{{
#!CommitTicketReference repository=""
revision="70845c6809f53d9d4029d760aa0118a47b92cb9d"
[1.7.x] Refs #24163 -- Fixed failing Oracle test when migrating from
ForeignKey to OneToOneField
Thanks Tim Graham for review
Backport of 64ecb3f07db4be5eef4d9eb7687f783ee446c82f from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:13>
* status: new => closed
* resolution: => fixed
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:14>
Comment (by claudep):
Just to be sure, was the Oracle failure due to an introspection issue with
`get_constraints` on Oracle? If the latter, is there a ticket about it?
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:15>
Comment (by MarkusH):
I haven't figured that out yet. But I'm investing and I'll open an issue
if it's another bug.
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:16>
Comment (by MarkusH):
The issue seems to be some kind of query caching on the cx_oracle or
Oracle layer. Unless we re-connect to the database, I don't see a way to
make that work.
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:17>
Comment (by shaib):
I finally figured out what's going on here, and why it was hard to
reproduce. The issue is actually within our control and can be solved once
and for all; then we'll be able to remove the
`connection_persists_old_columns` database feature. See #24200.
--
Ticket URL: <https://code.djangoproject.com/ticket/24163#comment:18>