]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
add test for issue 1743
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 1 Nov 2025 02:35:49 +0000 (22:35 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 1 Nov 2025 04:52:22 +0000 (00:52 -0400)
however this issue looks to be simple sqlite reflection issue
on sqlalchemy side

also fixes the incorrect exclusions code from 20c108720d7127ca.
just skip entire test if SQLite fk reflection is not there.
this exclusion should not have been added originally, it looks
like this was mistaken for a limitation when it really was a bug
in sqlite reflection

Change-Id: I3f51ebaf01f41dba86cea0aa31be28334401887b

alembic/testing/requirements.py
alembic/testing/suite/test_autogen_fks.py
tests/requirements.py
tests/test_autogen_diffs.py

index 7ec026b4955c18719f17d2b5ab295cc03d3b9011..1b217c937a578b2c596c83b99dfc967b1f78f776 100644 (file)
@@ -164,6 +164,10 @@ class SuiteRequirements(Requirements):
 
     @property
     def fk_names(self):
+        return self.foreign_key_name_reflection
+
+    @property
+    def foreign_key_name_reflection(self):
         return exclusions.open()
 
     @property
index 355e244c73d1ca82fad590ef22fae23b639d1b10..d69736e64d0f18f1e7359ba9dc56b1111de9d23f 100644 (file)
@@ -199,7 +199,7 @@ class AutogenerateForeignKeysTest(AutogenFixtureTest, TestBase):
 
         eq_(diffs, [])
 
-    @config.requirements.fk_names
+    @config.requirements.foreign_key_name_reflection
     def test_casing_convention_changed_so_put_drops_first(self):
         m1 = MetaData()
         m2 = MetaData()
index b8c8a680838a5b5b46714ba968299c3ea18feba3..081e5f858005137c69c893d5cdbaf2a931990870 100644 (file)
@@ -61,13 +61,14 @@ class DefaultRequirements(SuiteRequirements):
         return exclusions.only_on(["sqlite"])
 
     @property
-    def fk_names(self):
+    def foreign_key_name_reflection(self):
         """backend can reflect foreign key names"""
 
         # issue here was fixed in SQLAlchemy #12954 for sqlite, 2.0
         # release
-        return exclusions.fails_if(
-            lambda config: not sqla_compat.sqla_2 and config.against("sqlite")
+        return exclusions.skip_if(
+            lambda config: not sqla_compat.sqla_2
+            and exclusions.against(config, "sqlite")
         )
 
     @property
index 174cfac511acc0db27cd20187eea04ca42051415..cd9d54ae7aca300e44182d8159531f68ce5e014c 100644 (file)
@@ -1910,3 +1910,98 @@ class MultipleMetaDataTest(AutogenFixtureTest, TestBase):
             [m1a, m1b],
             [m2a, m2b],
         )
+
+
+class AutogenFKTest(AutogenFixtureTest, TestBase):
+    """Test foreign key constraint handling in autogenerate."""
+
+    __backend__ = True
+    __requires__ = ("foreign_key_constraint_reflection",)
+
+    @testing.variation("case", ["uppercase", "lowercase"])
+    @testing.variation("use_naming_convention", [True, False])
+    @config.requirements.foreign_key_name_reflection
+    def test_drop_fk_with_mixed_case_name(self, case, use_naming_convention):
+        """Test #1743"""
+        if case.uppercase:
+            fk_pattern = (
+                "FK_%(table_name)s_%(column_0_name)s_%(referred_table_name)s"
+            )
+            expected_name = "FK_child_parent_id_parent"
+        else:
+            fk_pattern = (
+                "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s"
+            )
+            expected_name = "fk_child_parent_id_parent"
+
+        if use_naming_convention:
+            m1 = MetaData(naming_convention={"fk": fk_pattern})
+        else:
+            m1 = MetaData()
+
+        Table(
+            "parent",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("name", String(50)),
+        )
+
+        c = Table(
+            "child",
+            m1,
+            Column("id", Integer, primary_key=True),
+            Column("name", String(50)),
+            Column("parent_id", Integer),
+            (
+                ForeignKeyConstraint(["parent_id"], ["parent.id"])
+                if use_naming_convention
+                else ForeignKeyConstraint(
+                    ["parent_id"], ["parent.id"], name=expected_name
+                )
+            ),
+        )
+
+        eq_(
+            [
+                fk
+                for fk in c.constraints
+                if isinstance(fk, ForeignKeyConstraint)
+            ][0].name,
+            expected_name,
+        )
+
+        if use_naming_convention:
+            m2 = MetaData(naming_convention={"fk": fk_pattern})
+        else:
+            m2 = MetaData()
+
+        Table(
+            "parent",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("name", String(50)),
+        )
+
+        Table(
+            "child",
+            m2,
+            Column("id", Integer, primary_key=True),
+            Column("name", String(50)),
+            Column("parent_id", Integer),
+        )
+
+        diffs = self._fixture(m1, m2)
+
+        # Should detect the FK removal
+        eq_(len(diffs), 1, f"Expected 1 diff, got {len(diffs)}: {diffs}")
+
+        # Verify it's a remove_fk operation with the correct name
+        self._assert_fk_diff(
+            diffs[0],
+            "remove_fk",
+            "child",
+            ["parent_id"],
+            "parent",
+            ["id"],
+            name=expected_name,
+        )