]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
assign variant mapping on adapt()
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 20 Mar 2024 14:23:41 +0000 (10:23 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 20 Mar 2024 15:43:30 +0000 (11:43 -0400)
Fixed regression from the 1.4 series where the refactor of the
:meth:`_types.TypeEngine.with_variant` method introduced at
:ref:`change_6980` failed to accommodate for the ``.copy()`` method, which
will lose the variant mappings that are set up. This becomes an issue for
the very specific case of a "schema" type, which includes types such as
:class:`.Enum` and :class:`.ARRAY`, when they are then used in the context
of an ORM Declarative mapping with mixins where copying of types comes into
play.  The variant mapping is now copied as well.

Fixes: #11176
Change-Id: Icf1a2752f60fce863c87ead8b0fe298b0f3d3766

doc/build/changelog/unreleased_20/11176.rst [new file with mode: 0644]
lib/sqlalchemy/sql/type_api.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_20/11176.rst b/doc/build/changelog/unreleased_20/11176.rst
new file mode 100644 (file)
index 0000000..cc35ab1
--- /dev/null
@@ -0,0 +1,12 @@
+.. change::
+    :tag: bug, sql, regression
+    :tickets: 11176
+
+    Fixed regression from the 1.4 series where the refactor of the
+    :meth:`_types.TypeEngine.with_variant` method introduced at
+    :ref:`change_6980` failed to accommodate for the ``.copy()`` method, which
+    will lose the variant mappings that are set up. This becomes an issue for
+    the very specific case of a "schema" type, which includes types such as
+    :class:`.Enum` and :class:`.ARRAY`, when they are then used in the context
+    of an ORM Declarative mapping with mixins where copying of types comes into
+    play.  The variant mapping is now copied as well.
index b638d6e265d32341c0883288904663052fedd2b2..38f96780c2fe44c2f23a9a1d61bfd388fdc74b8c 100644 (file)
@@ -1005,9 +1005,11 @@ class TypeEngine(Visitable, Generic[_T]):
         types with "implementation" types that are specific to a particular
         dialect.
         """
-        return util.constructor_copy(
+        typ = util.constructor_copy(
             self, cast(Type[TypeEngine[Any]], cls), **kw
         )
+        typ._variant_mapping = self._variant_mapping
+        return typ
 
     def coerce_compared_value(
         self, op: Optional[OperatorType], value: Any
index 898d6fa0a8c500ddbc40202c7312b4085f5b2983..0127004438cdfbd1aedcaf6cd3ccd3827046b642 100644 (file)
@@ -1695,6 +1695,19 @@ class VariantTest(fixtures.TestBase, AssertsCompiledSQL):
         )
         self.composite = self.variant.with_variant(self.UTypeThree(), "mysql")
 
+    def test_copy_doesnt_lose_variants(self):
+        """test #11176"""
+
+        v = self.UTypeOne().with_variant(self.UTypeTwo(), "postgresql")
+
+        v_c = v.copy()
+
+        self.assert_compile(v_c, "UTYPEONE", dialect="default")
+
+        self.assert_compile(
+            v_c, "UTYPETWO", dialect=dialects.postgresql.dialect()
+        )
+
     def test_one_dialect_is_req(self):
         with expect_raises_message(
             exc.ArgumentError, "At least one dialect name is required"