diff options
author | Tomasz Zielinski <tomasz.zielinski@pyconsultant.eu> | 2012-01-26 01:25:31 +0100 |
---|---|---|
committer | Tomasz Zielinski <tomasz.zielinski@pyconsultant.eu> | 2012-01-26 01:25:31 +0100 |
commit | 203fa05371c32bac09020fd4903addbaa8de8526 (patch) | |
tree | 58c786acd87045aba1fe6d1d831aee70ed0df209 | |
parent | eb765ca1625f1c82bf8b8e51c26a656c43255204 (diff) | |
download | askbot-203fa05371c32bac09020fd4903addbaa8de8526.tar.gz askbot-203fa05371c32bac09020fd4903addbaa8de8526.tar.bz2 askbot-203fa05371c32bac09020fd4903addbaa8de8526.zip |
Upgraded migrations to make them work for MySQL+InnoDB - BETA version
9 files changed, 142 insertions, 12 deletions
diff --git a/askbot/deps/django_authopenid/migrations/0002_make_multiple_openids_possible.py b/askbot/deps/django_authopenid/migrations/0002_make_multiple_openids_possible.py index 4e615e65..e5541286 100644 --- a/askbot/deps/django_authopenid/migrations/0002_make_multiple_openids_possible.py +++ b/askbot/deps/django_authopenid/migrations/0002_make_multiple_openids_possible.py @@ -4,6 +4,9 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +from askbot.migrations import houston_do_we_have_a_problem + + class Migration(SchemaMigration): def forwards(self, orm): @@ -12,6 +15,10 @@ class Migration(SchemaMigration): db.add_column('django_authopenid_userassociation', 'provider_name', self.gf('django.db.models.fields.CharField')(default='unknown', max_length=64), keep_default=False) # Removing unique constraint on 'UserAssociation', fields ['user'] + if houston_do_we_have_a_problem('django_authopenid_userassociation'): + # In MySQL+InnoDB Foreign keys have to have some index on them, + # therefore before deleting the UNIQUE index we have to create an "ordinary" one + db.create_index('django_authopenid_userassociation', ['user_id']) db.delete_unique('django_authopenid_userassociation', ['user_id']) # Adding unique constraint on 'UserAssociation', fields ['provider_name', 'user'] diff --git a/askbot/migrations/0012_delete_some_unused_models.py b/askbot/migrations/0012_delete_some_unused_models.py index 8c0edf8e..3a0888ef 100644 --- a/askbot/migrations/0012_delete_some_unused_models.py +++ b/askbot/migrations/0012_delete_some_unused_models.py @@ -24,15 +24,15 @@ class Migration(SchemaMigration): # Deleting model 'Mention' db.delete_table(u'mention') - # Deleting model 'Book' - db.delete_table(u'book') - # Removing M2M table for field questions on 'Book' db.delete_table('book_question') # Deleting model 'BookAuthorRss' db.delete_table(u'book_author_rss') - + + # Deleting model 'Book' + db.delete_table(u'book') + def backwards(self, orm): diff --git a/askbot/migrations/0101_megadeath_of_q_a_c.py b/askbot/migrations/0101_megadeath_of_q_a_c.py index 7e63a999..2f04b4e4 100644 --- a/askbot/migrations/0101_megadeath_of_q_a_c.py +++ b/askbot/migrations/0101_megadeath_of_q_a_c.py @@ -5,12 +5,22 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models -from askbot.migrations import TERM_YELLOW, TERM_RESET +from askbot.migrations import TERM_YELLOW, TERM_RESET, innodb_ready_rename_column + class Migration(SchemaMigration): def forwards(self, orm): - db.rename_column('askbot_thread', 'accepted_answer_post_id', 'accepted_answer_id') + #db.rename_column('askbot_thread', 'accepted_answer_post_id', 'accepted_answer_id') + innodb_ready_rename_column( + orm=orm, + models=self.__class__.models, + table='askbot_thread', + old_column_name='accepted_answer_post_id', + new_column_name='accepted_answer_id', + app_model='askbot.thread', + new_field_name='accepted_answer' + ) # Deleting model 'Comment' db.delete_table(u'comment') diff --git a/askbot/migrations/0102_rename_post_fields_back_1.py b/askbot/migrations/0102_rename_post_fields_back_1.py index 9d155ddd..9c51aac6 100644 --- a/askbot/migrations/0102_rename_post_fields_back_1.py +++ b/askbot/migrations/0102_rename_post_fields_back_1.py @@ -4,10 +4,23 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +from askbot.migrations import innodb_ready_rename_column + + class Migration(SchemaMigration): def forwards(self, orm): - db.rename_column('askbot_questionview', 'question_post_id', 'question_id') + #db.rename_column('askbot_questionview', 'question_post_id', 'question_id') + innodb_ready_rename_column( + orm=orm, + models=self.__class__.models, + table='askbot_questionview', + old_column_name='question_post_id', + new_column_name='question_id', + app_model='askbot.questionview', + new_field_name='question' + ) + def backwards(self, orm): diff --git a/askbot/migrations/0103_rename_post_fields_back_2.py b/askbot/migrations/0103_rename_post_fields_back_2.py index 6640ff83..f56e2258 100644 --- a/askbot/migrations/0103_rename_post_fields_back_2.py +++ b/askbot/migrations/0103_rename_post_fields_back_2.py @@ -4,10 +4,23 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +from askbot.migrations import innodb_ready_rename_column + + class Migration(SchemaMigration): def forwards(self, orm): - db.rename_column(u'activity', 'question_post_id', 'question_id') + #db.rename_column(u'activity', 'question_post_id', 'question_id') + innodb_ready_rename_column( + orm=orm, + models=self.__class__.models, + table='activity', + old_column_name='question_post_id', + new_column_name='question_id', + app_model='askbot.activity', + new_field_name='question' + ) + def backwards(self, orm): diff --git a/askbot/migrations/0104_auto__del_field_repute_question_post__add_field_repute_question.py b/askbot/migrations/0104_auto__del_field_repute_question_post__add_field_repute_question.py index 4044cef1..ed72e1ec 100644 --- a/askbot/migrations/0104_auto__del_field_repute_question_post__add_field_repute_question.py +++ b/askbot/migrations/0104_auto__del_field_repute_question_post__add_field_repute_question.py @@ -4,10 +4,23 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +from askbot.migrations import innodb_ready_rename_column + + class Migration(SchemaMigration): def forwards(self, orm): - db.rename_column(u'repute', 'question_post_id', 'question_id') + #db.rename_column(u'repute', 'question_post_id', 'question_id') + innodb_ready_rename_column( + orm=orm, + models=self.__class__.models, + table='repute', + old_column_name='question_post_id', + new_column_name='question_id', + app_model='askbot.repute', + new_field_name='question' + ) + def backwards(self, orm): diff --git a/askbot/migrations/0105_restore_anon_ans_q.py b/askbot/migrations/0105_restore_anon_ans_q.py index 05429728..4bf5ca99 100644 --- a/askbot/migrations/0105_restore_anon_ans_q.py +++ b/askbot/migrations/0105_restore_anon_ans_q.py @@ -4,10 +4,23 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +from askbot.migrations import innodb_ready_rename_column + + class Migration(SchemaMigration): def forwards(self, orm): - db.rename_column('askbot_anonymousanswer', 'question_post_id', 'question_id') + #db.rename_column('askbot_anonymousanswer', 'question_post_id', 'question_id') + innodb_ready_rename_column( + orm=orm, + models=self.__class__.models, + table='askbot_anonymousanswer', + old_column_name='question_post_id', + new_column_name='question_id', + app_model='askbot.anonymousanswer', + new_field_name='question' + ) + def backwards(self, orm): diff --git a/askbot/migrations/0106_update_postgres_full_text_setup.py b/askbot/migrations/0106_update_postgres_full_text_setup.py index b0b0c668..e788879c 100644 --- a/askbot/migrations/0106_update_postgres_full_text_setup.py +++ b/askbot/migrations/0106_update_postgres_full_text_setup.py @@ -15,8 +15,7 @@ class Migration(DataMigration): def forwards(self, orm): "Write your forwards methods here." - if 'test' in sys.argv: - return # Somehow this migration fails when called from test runner + return # TODO: remove me when the SQL is fixed! if 'postgresql_psycopg2' in askbot.get_database_engine_name(): script_path = os.path.join( diff --git a/askbot/migrations/__init__.py b/askbot/migrations/__init__.py index ac6b3d47..86377b7b 100644 --- a/askbot/migrations/__init__.py +++ b/askbot/migrations/__init__.py @@ -1,3 +1,6 @@ +from south.db import db +from south.utils import ask_for_it_by_name + # Terminal ANSI codes for printing colored text: # - http://code.google.com/p/testoob/source/browse/trunk/src/testoob/reporting/colored.py#20 # - http://stackoverflow.com/questions/287871/print-in-terminal-with-colors-using-python @@ -5,3 +8,62 @@ TERM_RED_BOLD = '\x1b[31;01m\x1b[01m' TERM_YELLOW = "\x1b[33;01m" TERM_GREEN = "\x1b[32;06m" TERM_RESET = '\x1b[0m' + +def houston_do_we_have_a_problem(table): + "Checks if we're using MySQL + InnoDB" + if not db.dry_run and db.backend_name == 'mysql': + db_table = [db._get_connection().settings_dict['NAME'], table] + ret = db.execute( + "SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES " + "where TABLE_SCHEMA = %s and TABLE_NAME = %s", + db_table + ) + assert len(ret) == 1 # There HAVE to be info about this table ! + assert len(ret[0]) == 2 + if ret[0][1] == 'InnoDB': + print TERM_YELLOW, "!!!", '.'.join(db_table), "is InnoDB - using workarounds !!!", TERM_RESET + return True + return False + + +def innodb_ready_rename_column(orm, models, table, old_column_name, new_column_name, app_model, new_field_name): + """ + Foreign key renaming which works for InnoDB + More: http://south.aeracode.org/ticket/466 + + Parameters: + - orm: a reference to 'orm' parameter passed to Migration.forwards()/backwards() + - models: reference to Migration.models data structure + - table: e.g. 'askbot_thread' + - old_column_name: e.g. 'question_post_id' + - new_column_name: e.g. 'question_id' + - app_model: e.g. 'askbot.thread' (should be a dict key into 'models') + - new_field_name: e.g. 'question' (usually it's same as new_column_name, only without trailing '_id') + """ + use_workaround = houston_do_we_have_a_problem(table) + + # ditch the foreign key + if use_workaround: + db.delete_foreign_key(table, old_column_name) + + # rename column + db.rename_column(table, old_column_name, new_column_name) + + # restore the foreign key + if not use_workaround: + return + + model_def = models[app_model][new_field_name] + assert model_def[0] == 'django.db.models.fields.related.ForeignKey' + # Copy the dict so that we don't change the original + # (otherwise the dry run would change it for the "normal" run + # and the latter would try to convert str to model once again) + fkey_params = model_def[2].copy() + assert 'to' in fkey_params + assert fkey_params['to'].startswith("orm['") + assert fkey_params['to'].endswith("']") + fkey_params['to'] = orm[fkey_params['to'][5:-2]] # convert "orm['app.models']" string to actual model + field = ask_for_it_by_name(model_def[0])(**fkey_params) + # INFO: ask_for_it_by_name() if equivalent to self.gf() which is usually used in migrations, e.g.: + # db.alter_column('askbot_badgedata', 'slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)) + db.alter_column(table, new_column_name, field) |