Created
February 24, 2011 02:43
-
-
Save kylemacfarlane/841659 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
import datetime | |
from south.db import db | |
from south.v2 import SchemaMigration | |
from django.db import models | |
class Migration(SchemaMigration): | |
# This can get stupid. When running all migrations from scratch such as | |
# during tests then dependant apps will need to be initialised before this | |
# migration otherwise there will be a data type mismatch. But all those apps | |
# will need to depend on 0001_inital from this app (or put needed by in | |
# there). | |
depends_on = ( | |
('downloads', '0001_initial'), | |
) | |
def get_fks(self, table, column, db_name=None): | |
if db_name is None: | |
# We need the database name or things go crazy in tests or other | |
# cases where the database user might have access to more than one | |
# database. | |
if db.backend_name == 'mysql': | |
db_name = db.execute('SELECT database()')[0][0] | |
elif db.backend_name == 'postgres': | |
db_name = db.execute('SELECT current_database()')[0][0] | |
if db.backend_name == 'mysql': | |
query = """ | |
SELECT DISTINCT | |
table_name, column_name, constraint_name, referenced_table_name, referenced_column_name | |
FROM | |
information_schema.key_column_usage | |
WHERE | |
referenced_table_schema = '%s' | |
AND referenced_table_name = '%s' | |
AND referenced_column_name = '%s' | |
""" | |
elif db.backend_name == 'postgres': | |
query = """ | |
SELECT DISTINCT | |
kcu.table_name, kcu.column_name, kcu.constraint_name, ccu.table_name, ccu.column_name | |
FROM | |
information_schema.table_constraints AS tc | |
JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name | |
JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name | |
WHERE | |
tc.constraint_type = 'FOREIGN KEY' | |
AND kcu.table_catalog = '%s' | |
AND ccu.table_name = '%s' | |
AND ccu.column_name = '%s' | |
""" | |
fks = db.execute(query % (db_name, table, column)) | |
child_fks = [] | |
for fk in fks: | |
child_fks = child_fks + self.get_fks(fk[0], fk[1], db_name) | |
return list(fks) + child_fks | |
def get_and_drop_fks(self, table, column): | |
fks = [] | |
if db.backend_name in ('mysql', 'postgres') and not db.dry_run: | |
fks = self.get_fks(table, column) | |
for fk in fks: | |
if db.backend_name == 'mysql': | |
query = 'ALTER TABLE %s DROP FOREIGN KEY %s' | |
elif db.backend_name == 'postgres': | |
query = 'ALTER TABLE %s DROP CONSTRAINT %s' | |
db.execute(query % (fk[0], fk[2])) | |
return fks | |
def update_fks(self, fks, field): | |
for fk in fks: | |
# This loses whether or not a field allows NULL. | |
db.alter_column(fk[0], fk[1], field) | |
# Add FKs after all columns have been altered to prevent data type | |
# conflicts. | |
for fk in fks: | |
db.execute( | |
'ALTER TABLE %s ADD CONSTRAINT ' | |
'%s FOREIGN KEY (%s) ' | |
'REFERENCES %s(%s)' | |
% (fk[0], fk[2], fk[1], fk[3], fk[4]) | |
) | |
def forwards(self, orm): | |
fks = self.get_and_drop_fks('shop_order', 'id') | |
db.alter_column('shop_order', 'id', self.gf('django.db.models.fields.CharField')(max_length=16, primary_key=True)) | |
self.update_fks(fks, self.gf('django.db.models.fields.CharField')(max_length=16, primary_key=True)) | |
fks = self.get_and_drop_fks('shop_credit_note', 'id') | |
db.alter_column('shop_credit_note', 'id', self.gf('django.db.models.fields.CharField')(max_length=16, primary_key=True)) | |
self.update_fks(fks, self.gf('django.db.models.fields.CharField')(max_length=16, primary_key=True)) | |
def backwards(self, orm): | |
fks = self.get_and_drop_fks('shop_order', 'id') | |
db.alter_column('shop_order', 'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)) | |
self.update_fks(fks, self.gf('django.db.models.fields.AutoField')(primary_key=True)) | |
fks = self.get_and_drop_fks('shop_credit_note', 'id') | |
db.alter_column('shop_credit_note', 'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)) | |
self.update_fks(fks, self.gf('django.db.models.fields.AutoField')(primary_key=True)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment