Fix foreign key and primary key errors in db scripts

Starting from 10.1.x of MariaDB and 5.6 of MySQL, they not allow
changes to primary key and foreign key columns after the definitions
creation. This breaks db alembic scripts with
IntegrityError constraints.

Fix db scripts to drop the foreign key constraint and add them back
once the definitions are modified in existing schemas.

Change-Id: I4a4faa1e6d0aafc26f2a56986f83c4c4f0cfc763
Closes-Bug: #1594807
This commit is contained in:
Sripriya 2016-06-30 18:16:34 -07:00 committed by Sripriya Seetharam
parent 5b5cd503f6
commit 625b7e707c
3 changed files with 70 additions and 24 deletions

View File

@ -13,7 +13,9 @@
# under the License.
from alembic import op
import contextlib
import sqlalchemy as sa
from sqlalchemy.engine import reflection
def alter_enum(table, column, enum_type, nullable):
@ -35,3 +37,38 @@ def alter_enum(table, column, enum_type, nullable):
else:
op.alter_column(table, column, type_=enum_type,
existing_nullable=nullable)
def create_foreign_key_constraint(table_name, fk_constraints):
for fk in fk_constraints:
op.create_foreign_key(
constraint_name=fk['name'],
source_table=table_name,
referent_table=fk['referred_table'],
local_cols=fk['constrained_columns'],
remote_cols=fk['referred_columns'],
ondelete=fk['options'].get('ondelete')
)
def drop_foreign_key_constraint(table_name, fk_constraints):
for fk in fk_constraints:
op.drop_constraint(
constraint_name=fk['name'],
table_name=table_name,
type_='foreignkey'
)
@contextlib.contextmanager
def modify_foreign_keys_constraint(table_names):
inspector = reflection.Inspector.from_engine(op.get_bind())
try:
for table in table_names:
fk_constraints = inspector.get_foreign_keys(table)
drop_foreign_key_constraint(table, fk_constraints)
yield
finally:
for table in table_names:
fk_constraints = inspector.get_foreign_keys(table)
create_foreign_key_constraint(table, fk_constraints)

View File

@ -27,17 +27,19 @@ down_revision = '12a57080b277'
from alembic import op
from sqlalchemy.dialects import mysql
from tacker.db import migration
def upgrade(active_plugins=None, options=None):
# commands auto generated by Alembic - please adjust! #
op.alter_column(u'deviceattributes', 'device_id',
existing_type=mysql.VARCHAR(length=255),
nullable=False)
op.alter_column(u'devices', 'status',
existing_type=mysql.VARCHAR(length=255),
nullable=False)
# end Alembic commands #
fk_constraint = ('deviceattributes', )
with migration.modify_foreign_keys_constraint(fk_constraint):
op.alter_column(u'deviceattributes', 'device_id',
existing_type=mysql.VARCHAR(length=255),
nullable=False)
op.alter_column(u'devices', 'status', existing_type=mysql.VARCHAR(
length=255), nullable=False)
# end Alembic commands #s
def downgrade(active_plugins=None, options=None):

View File

@ -28,28 +28,35 @@ down_revision = 'acf941e54075'
from alembic import op
from tacker.db import migration
from tacker.db import types
FK_MAP = {'vims': ('vimauths', 'devices'), 'devices': ('deviceattributes',
'proxymgmtports'), 'devicetemplates': ('devices', 'servicetypes',
'devicetemplateattributes')}
def upgrade(active_plugins=None, options=None):
for table in ['vims', 'vimauths', 'devices', 'deviceattributes',
pk_id_tables = ('vims', 'vimauths', 'devices', 'deviceattributes',
'servicetypes', 'devicetemplates',
'devicetemplateattributes']:
op.alter_column(table,
'id',
type_=types.Uuid)
'devicetemplateattributes')
for table in pk_id_tables:
with migration.modify_foreign_keys_constraint(FK_MAP.get(table, [])):
op.alter_column(table, 'id', type_=types.Uuid)
for table in ['devices', 'servicetypes', 'devicetemplateattributes']:
op.alter_column(table,
'template_id',
type_=types.Uuid)
fk_template_id_tables = ('devices', 'servicetypes',
'devicetemplateattributes')
for table in fk_template_id_tables:
with migration.modify_foreign_keys_constraint(fk_template_id_tables):
op.alter_column(table, 'template_id', type_=types.Uuid)
for table in ['devices', 'vimauths']:
op.alter_column(table,
'vim_id',
type_=types.Uuid)
fk_vim_id_tables = ('devices', 'vimauths')
for table in fk_vim_id_tables:
with migration.modify_foreign_keys_constraint(fk_vim_id_tables):
op.alter_column(table, 'vim_id', type_=types.Uuid)
for table in ['deviceattributes', 'proxymgmtports']:
op.alter_column(table,
'device_id',
type_=types.Uuid)
fk_device_id_tables = ('deviceattributes', 'proxymgmtports')
for table in fk_device_id_tables:
with migration.modify_foreign_keys_constraint(fk_device_id_tables):
op.alter_column(table, 'device_id', type_=types.Uuid)