From ba6705a731f8a80f9d01e88ae3425a93d70e4688 Mon Sep 17 00:00:00 2001 From: Ilya Pekelny Date: Tue, 1 Apr 2014 12:17:10 +0300 Subject: [PATCH] Explicit foreign key indexes. Overview: MySQL requires indexes on foreign keys. Such an index is created on the referencing table automatically if it does not exist. Motivation: MySQL names foreign keys indexes differently dependent from itself version. Implicit fk indexes is MySQL specific behavior, so it should be ignored during comparision. We plan to use Alembic to compare models and migrations I0758c7e09d1d46ce870c3f94f76c2a177955e143. Alembic doesn't support 5.5 naming convention. So we need consistent index name for all MySQL versions to be easily ignored. Solution: A new migration script renames incorrectly named fk indexes on MySQL. Reproduction: Stop execution when foregn keys will be initialized. See schema with your MySQL shell client. With 5.5, indexes which was not named explicitly, will have a name such as __fk, with 5.1 it will be . Change-Id: I01ba0c8856afbda59394395ac319bf83a55ee2be Partial-Bug: #1292591 --- .../versions/050_fk_consistent_indexes.py | 49 +++++++++++++++++++ .../versions/005_consumer_id_index.py | 42 ++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 keystone/common/sql/migrate_repo/versions/050_fk_consistent_indexes.py create mode 100644 keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py diff --git a/keystone/common/sql/migrate_repo/versions/050_fk_consistent_indexes.py b/keystone/common/sql/migrate_repo/versions/050_fk_consistent_indexes.py new file mode 100644 index 000000000..535a09444 --- /dev/null +++ b/keystone/common/sql/migrate_repo/versions/050_fk_consistent_indexes.py @@ -0,0 +1,49 @@ +# Copyright 2014 Mirantis.inc +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sqlalchemy as sa + + +def upgrade(migrate_engine): + + if migrate_engine.name == 'mysql': + meta = sa.MetaData(bind=migrate_engine) + endpoint = sa.Table('endpoint', meta, autoload=True) + + # NOTE(i159): MySQL requires indexes on referencing columns, and those + # indexes create automatically. That those indexes will have different + # names, depending on version of MySQL used. We shoud make this naming + # consistent, by reverting index name to a consistent condition. + if any(i for i in endpoint.indexes if + i.columns.keys() == ['service_id'] and i.name != 'service_id'): + # NOTE(i159): by this action will be made re-creation of an index + # with the new name. This can be considered as renaming under the + # MySQL rules. + sa.Index('service_id', endpoint.c.service_id).create() + + user_group_membership = sa.Table('user_group_membership', + meta, autoload=True) + + if any(i for i in user_group_membership.indexes if + i.columns.keys() == ['group_id'] and i.name != 'group_id'): + sa.Index('group_id', user_group_membership.c.group_id).create() + + +def downgrade(migrate_engine): + # NOTE(i159): index exists only in MySQL schemas, and got an inconsistent + # name only when MySQL 5.5 renamed it after re-creation + # (during migrations). So we just fixed inconsistency, there is no + # necessity to revert it. + pass diff --git a/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py b/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py new file mode 100644 index 000000000..428971f84 --- /dev/null +++ b/keystone/contrib/oauth1/migrate_repo/versions/005_consumer_id_index.py @@ -0,0 +1,42 @@ +# Copyright 2014 Mirantis.inc +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sqlalchemy as sa + + +def upgrade(migrate_engine): + + if migrate_engine.name == 'mysql': + meta = sa.MetaData(bind=migrate_engine) + table = sa.Table('access_token', meta, autoload=True) + + # NOTE(i159): MySQL requires indexes on referencing columns, and those + # indexes create automatically. That those indexes will have different + # names, depending on version of MySQL used. We shoud make this naming + # consistent, by reverting index name to a consistent condition. + if any(i for i in table.indexes if i.columns.keys() == ['consumer_id'] + and i.name != 'consumer_id'): + # NOTE(i159): by this action will be made re-creation of an index + # with the new name. This can be considered as renaming under the + # MySQL rules. + sa.Index('consumer_id', table.c.consumer_id).create() + + +def downgrade(migrate_engine): + # NOTE(i159): index exists only in MySQL schemas, and got an inconsistent + # name only when MySQL 5.5 renamed it after re-creation + # (during migrations). So we just fixed inconsistency, there is no + # necessity to revert it. + pass