diff --git a/ceilometer/storage/sqlalchemy/migrate_repo/versions/012_add_missing_foreign_keys.py b/ceilometer/storage/sqlalchemy/migrate_repo/versions/012_add_missing_foreign_keys.py index f95faea5..beb3074a 100644 --- a/ceilometer/storage/sqlalchemy/migrate_repo/versions/012_add_missing_foreign_keys.py +++ b/ceilometer/storage/sqlalchemy/migrate_repo/versions/012_add_missing_foreign_keys.py @@ -15,6 +15,9 @@ from migrate import ForeignKeyConstraint from sqlalchemy import MetaData, Table +from sqlalchemy.sql.expression import select + +from ceilometer.openstack.common.db.sqlalchemy import utils TABLES = ['resource', 'sourceassoc', 'user', 'project', 'meter', 'source', 'alarm'] @@ -36,13 +39,28 @@ INDEXES = { def upgrade(migrate_engine): + if migrate_engine.name == 'sqlite': + return meta = MetaData(bind=migrate_engine) load_tables = dict((table_name, Table(table_name, meta, autoload=True)) for table_name in TABLES) for table_name, indexes in INDEXES.items(): table = load_tables[table_name] + + # Save data that conflicted with FK. + columns = [column.copy() for column in table.columns] + table_dump = Table('dump_' + table_name, meta, *columns) + table_dump.create() for column, ref_table_name, ref_column_name in indexes: ref_table = load_tables[ref_table_name] + subq = select([getattr(ref_table.c, ref_column_name)]) + sql = utils.InsertFromSelect(table_dump, table.select().where( + ~ getattr(table.c, column).in_(subq))) + sql_del = table.delete().where( + ~ getattr(table.c, column).in_(subq)) + migrate_engine.execute(sql) + migrate_engine.execute(sql_del) + params = {'columns': [table.c[column]], 'refcolumns': [ref_table.c[ref_column_name]]} if migrate_engine.name == 'mysql': @@ -52,6 +70,8 @@ def upgrade(migrate_engine): def downgrade(migrate_engine): + if migrate_engine.name == 'sqlite': + return meta = MetaData(bind=migrate_engine) load_tables = dict((table_name, Table(table_name, meta, autoload=True)) for table_name in TABLES) @@ -63,5 +83,13 @@ def downgrade(migrate_engine): 'refcolumns': [ref_table.c[ref_column_name]]} if migrate_engine.name == 'mysql': params['name'] = "_".join(('fk', table_name, column)) - fkey = ForeignKeyConstraint(**params) - fkey.drop() + with migrate_engine.begin(): + fkey = ForeignKeyConstraint(**params) + fkey.drop() + with migrate_engine.begin(): + # Restore data that had been dropped. + table_dump_name = 'dump_' + table_name + table_dump = Table(table_dump_name, meta, autoload=True) + sql = utils.InsertFromSelect(table, table_dump.select()) + migrate_engine.execute(sql) + table_dump.drop()