diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2023-05-12 21:15:55 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2023-05-12 21:15:55 +0000 |
commit | 32a82f7e4d18c0c1459a30cd91e2265971de10f8 (patch) | |
tree | 2a9c7ffdcc6f2fa5a5c51a292c9a361541b557cf | |
parent | 86d1178e7e96dfd790b5db3cab28b06904c4e22e (diff) | |
parent | 8ba4a4435871fe948f8292e7bb5bbc452e7d51ca (diff) | |
download | alembic-32a82f7e4d18c0c1459a30cd91e2265971de10f8.tar.gz |
Merge "dont compare unique constraint and index sigs to each other" into main
-rw-r--r-- | alembic/autogenerate/compare.py | 12 | ||||
-rw-r--r-- | docs/build/unreleased/1240.rst | 8 | ||||
-rw-r--r-- | tests/test_autogen_indexes.py | 74 |
3 files changed, 89 insertions, 5 deletions
diff --git a/alembic/autogenerate/compare.py b/alembic/autogenerate/compare.py index b489328..5727891 100644 --- a/alembic/autogenerate/compare.py +++ b/alembic/autogenerate/compare.py @@ -452,7 +452,9 @@ class _uq_constraint_sig(_constraint_sig): def __init__(self, const: UniqueConstraint) -> None: self.const = const self.name = const.name - self.sig = tuple(sorted([col.name for col in const.columns])) + self.sig = ("UNIQUE_CONSTRAINT",) + tuple( + sorted([col.name for col in const.columns]) + ) @property def column_names(self) -> List[str]: @@ -465,7 +467,7 @@ class _ix_constraint_sig(_constraint_sig): def __init__(self, const: Index, impl: DefaultImpl) -> None: self.const = const self.name = const.name - self.sig = impl.create_index_sig(const) + self.sig = ("INDEX",) + impl.create_index_sig(const) self.is_unique = bool(const.unique) def md_name_to_sql_name(self, context: AutogenContext) -> Optional[str]: @@ -807,11 +809,11 @@ def _compare_indexes_and_uniques( if not conn_obj.is_index and conn_obj.sig in unnamed_metadata_uniques: continue elif removed_name in doubled_constraints: + conn_uq, conn_idx = doubled_constraints[removed_name] if ( - conn_obj.sig not in metadata_indexes_by_sig - and conn_obj.sig not in metadata_uniques_by_sig + conn_idx.sig not in metadata_indexes_by_sig + and conn_uq.sig not in metadata_uniques_by_sig ): - conn_uq, conn_idx = doubled_constraints[removed_name] obj_removed(conn_uq) obj_removed(conn_idx) else: diff --git a/docs/build/unreleased/1240.rst b/docs/build/unreleased/1240.rst new file mode 100644 index 0000000..19cfd81 --- /dev/null +++ b/docs/build/unreleased/1240.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mysql, regression + :tickets: 1240 + + Fixed regression caused by :ticket:`1166` released in version 1.10.0 which + caused MySQL unique constraints with multiple columns to not compare + correctly within autogenerate, due to different sorting rules on unique + constraints vs. indexes, which in MySQL are shared constructs. diff --git a/tests/test_autogen_indexes.py b/tests/test_autogen_indexes.py index f697e5a..abefd66 100644 --- a/tests/test_autogen_indexes.py +++ b/tests/test_autogen_indexes.py @@ -463,6 +463,80 @@ class AutogenerateUniqueIndexTest(AutogenFixtureTest, TestBase): eq_(diffs, []) @config.requirements.unique_constraint_reflection + def test_nothing_changed_cols_unsorted(self): + """test #1240 + + + MySQL doubles unique constraints as indexes, so we need to make + sure we aren't comparing index sigs to unique constraint sigs, + which we were doing previously by mistake. As their signatures + were compatible, things "worked" but once index sigs changed + col name sorting order, it broke. + + """ + + m1 = MetaData() + m2 = MetaData() + + Table( + "nothing_changed", + m1, + Column("id", Integer, primary_key=True), + Column("sid", Integer, nullable=False), + Column("label", String(30), nullable=False), + Column("fid", Integer, nullable=False), + UniqueConstraint("sid", "label"), + UniqueConstraint("sid", "fid"), + ) + + Table( + "nothing_changed", + m2, + Column("id", Integer, primary_key=True), + Column("sid", Integer, nullable=False), + Column("label", String(30), nullable=False), + Column("fid", Integer, nullable=False), + UniqueConstraint("sid", "label"), + UniqueConstraint("sid", "fid"), + ) + + diffs = self._fixture(m1, m2) + eq_(diffs, []) + + @config.requirements.unique_constraint_reflection + @config.requirements.reports_unnamed_constraints + def test_remove_uq_constraint(self): + """supplementary test for codepath in #1240""" + + m1 = MetaData() + m2 = MetaData() + + Table( + "something_changed", + m1, + Column("id", Integer, primary_key=True), + Column("sid", Integer, nullable=False), + Column("label", String(30), nullable=False), + Column("fid", Integer, nullable=False), + UniqueConstraint("sid", "label"), + UniqueConstraint("sid", "fid"), + ) + + Table( + "something_changed", + m2, + Column("id", Integer, primary_key=True), + Column("sid", Integer, nullable=False), + Column("label", String(30), nullable=False), + Column("fid", Integer, nullable=False), + UniqueConstraint("sid", "fid"), + ) + + diffs = self._fixture(m1, m2) + assert len(diffs) == 1 + assert diffs[0][0] in ("remove_index", "remove_constraint") + + @config.requirements.unique_constraint_reflection def test_uq_casing_convention_changed_so_put_drops_first(self): m1 = MetaData() m2 = MetaData() |