Fix migration with fkeys
Creation of fkeys doesn't work in sqlite, so we should do these changes in another dialects. Fix bug 1204823. Also we can have a problem with data conflicted with declared ForeignKey. We should dump "bad" data to another place, upgrade and create FK. Downgrade method should restore dumped data. Change-Id: I33089d6f47dcde4cf716a3d303c8df23dd19cd07
This commit is contained in:
parent
b59a03109c
commit
650ad385ba
@ -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))
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user