]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Repair de-quoting logic used for pre-1.4 SQLAlchemy versions
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 6 Feb 2020 15:38:57 +0000 (10:38 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 6 Feb 2020 17:47:28 +0000 (12:47 -0500)
Fixed regression in 1.4.0 due to :ticket:`647` where unique constraint
comparison with mixed case constraint names while not using a naming
convention would produce false positives during autogenerate.

Change-Id: Ic3d60f7d44377cdb4937ac0bb2bc11d27d03b8bd
Fixes: #654
alembic/util/sqla_compat.py
docs/build/unreleased/654.rst [new file with mode: 0644]
tests/test_autogen_indexes.py

index c7b43d0ab70b340405927bf1f3ec471fb4cda334..82b65f1ec1667dbdf8829c6215a597affacee9ee 100644 (file)
@@ -8,6 +8,7 @@ from sqlalchemy.ext.compiler import compiles
 from sqlalchemy.schema import CheckConstraint
 from sqlalchemy.schema import Column
 from sqlalchemy.schema import ForeignKeyConstraint
+from sqlalchemy.sql.elements import quoted_name
 from sqlalchemy.sql.expression import _BindParamClause
 from sqlalchemy.sql.expression import _TextClause as TextClause
 from sqlalchemy.sql.visitors import traverse
@@ -214,14 +215,19 @@ def _get_constraint_final_name(constraint, dialect):
             # might be quoted_name, might be truncated_name, keep it the
             # same
             quoted_name_cls = type(constraint.name)
-            new_name = quoted_name_cls(str(constraint.name), quote=False)
-            constraint = constraint.__class__(name=new_name)
+        else:
+            quoted_name_cls = quoted_name
+
+        new_name = quoted_name_cls(str(constraint.name), quote=False)
+        constraint = constraint.__class__(name=new_name)
 
         if isinstance(constraint, schema.Index):
+            # name should not be quoted.
             return dialect.ddl_compiler(dialect, None)._prepared_index_name(
                 constraint
             )
         else:
+            # name should not be quoted.
             return dialect.identifier_preparer.format_constraint(constraint)
 
 
diff --git a/docs/build/unreleased/654.rst b/docs/build/unreleased/654.rst
new file mode 100644 (file)
index 0000000..e21bbd9
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, autogenerate
+    :tickets: 654
+
+    Fixed regression in 1.4.0 due to :ticket:`647` where unique constraint
+    comparison with mixed case constraint names while not using a naming
+    convention would produce false positives during autogenerate.
index 6a8800b2d8d08679ea92a81f75539f9011762382..fb5b3501ec37dd1aa09458b2724dc2713868c389 100644 (file)
@@ -365,6 +365,122 @@ class AutogenerateUniqueIndexTest(AutogenFixtureTest, TestBase):
         diffs = self._fixture(m1, m2, max_identifier_length=30)
         eq_(diffs, [])
 
+    def test_nothing_changed_uq_w_mixed_case_nconv_name(self):
+        m1 = MetaData(
+            naming_convention={
+                "ix": "index_%(table_name)s_%(column_0_label)s",
+                "uq": "unique_%(table_name)s_%(column_0_label)s",
+            }
+        )
+        m2 = MetaData(
+            naming_convention={
+                "ix": "index_%(table_name)s_%(column_0_label)s",
+                "uq": "unique_%(table_name)s_%(column_0_label)s",
+            }
+        )
+
+        Table(
+            "NothingChanged",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("XCol", Integer),
+            UniqueConstraint("XCol"),
+            mysql_engine="InnoDB",
+        )
+
+        Table(
+            "NothingChanged",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("XCol", Integer),
+            UniqueConstraint("XCol"),
+            mysql_engine="InnoDB",
+        )
+
+        diffs = self._fixture(m1, m2)
+        eq_(diffs, [])
+
+    def test_nothing_changed_uq_w_mixed_case_plain_name(self):
+        m1 = MetaData()
+        m2 = MetaData()
+
+        Table(
+            "nothing_changed",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("x", Integer),
+            UniqueConstraint("x", name="SomeConstraint"),
+            mysql_engine="InnoDB",
+        )
+
+        Table(
+            "nothing_changed",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("x", Integer),
+            UniqueConstraint("x", name="SomeConstraint"),
+            mysql_engine="InnoDB",
+        )
+        diffs = self._fixture(m1, m2)
+        eq_(diffs, [])
+
+    def test_nothing_changed_ix_w_mixed_case_plain_name(self):
+        m1 = MetaData()
+        m2 = MetaData()
+
+        Table(
+            "nothing_changed",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("x", Integer),
+            Index("SomeIndex", "x"),
+            mysql_engine="InnoDB",
+        )
+
+        Table(
+            "nothing_changed",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("x", Integer),
+            Index("SomeIndex", "x"),
+            mysql_engine="InnoDB",
+        )
+        diffs = self._fixture(m1, m2)
+        eq_(diffs, [])
+
+    def test_nothing_changed_ix_w_mixed_case_nconv_name(self):
+        m1 = MetaData(
+            naming_convention={
+                "ix": "index_%(table_name)s_%(column_0_label)s",
+                "uq": "unique_%(table_name)s_%(column_0_label)s",
+            }
+        )
+        m2 = MetaData(
+            naming_convention={
+                "ix": "index_%(table_name)s_%(column_0_label)s",
+                "uq": "unique_%(table_name)s_%(column_0_label)s",
+            }
+        )
+
+        Table(
+            "NothingChanged",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("XCol", Integer, index=True),
+            mysql_engine="InnoDB",
+        )
+
+        Table(
+            "NothingChanged",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("XCol", Integer, index=True),
+            mysql_engine="InnoDB",
+        )
+
+        diffs = self._fixture(m1, m2)
+        eq_(diffs, [])
+
     def test_nothing_changed_two(self):
         m1 = MetaData()
         m2 = MetaData()