]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
undefer column name sooner to accommodate composites
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 21 Feb 2022 21:56:16 +0000 (16:56 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 21 Feb 2022 21:56:16 +0000 (16:56 -0500)
This was from adding composite class introspection as a
means of determining column name, cols need to have their
normal attribute name set up already.

Fixes: #7751
Change-Id: I1fe61c135af9b1bf9bc289f683640e63bcc69045

lib/sqlalchemy/orm/decl_base.py
test/orm/test_composites.py

index 342aa772b046644d6abd809cf109e7a3b2b231d0..5c72371b29874430195ec0934104f0c6136bee2c 100644 (file)
@@ -833,6 +833,8 @@ class _ClassScanMapperConfig(_MapperConfig):
                     "for the MetaData instance when using a "
                     "declarative base class."
                 )
+            elif isinstance(value, Column):
+                _undefer_column_name(k, self.column_copies.get(value, value))
             elif isinstance(value, _IntrospectsAnnotations):
                 annotation, is_dataclass = self.collected_annotations.get(
                     k, (None, None)
@@ -865,7 +867,9 @@ class _ClassScanMapperConfig(_MapperConfig):
                     del our_stuff[key]
 
             elif isinstance(c, Column):
-                _undefer_column_name(key, c)
+                # undefer previously occurred here, and now occurs earlier.
+                # ensure every column we get here has been named
+                assert c.name is not None
                 name_to_prop_key[c.name].add(key)
                 declared_columns.add(c)
                 # if the column is the same name as the key,
index f41947b6c8efeb19a0014dd3938c1ee9ca6f38ee..afa3daf1356c2a09979d5cc73e1ac1907bb8e016 100644 (file)
@@ -425,6 +425,48 @@ class PointTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
         e = Edge()
         eq_(e.start, None)
 
+    def test_no_name_declarative(self, decl_base):
+        """test #7751"""
+
+        class Point:
+            def __init__(self, x, y):
+                self.x = x
+                self.y = y
+
+            def __composite_values__(self):
+                return self.x, self.y
+
+            def __repr__(self):
+                return "Point(x=%r, y=%r)" % (self.x, self.y)
+
+            def __eq__(self, other):
+                return (
+                    isinstance(other, Point)
+                    and other.x == self.x
+                    and other.y == self.y
+                )
+
+            def __ne__(self, other):
+                return not self.__eq__(other)
+
+        class Vertex(decl_base):
+            __tablename__ = "vertices"
+
+            id = Column(Integer, primary_key=True)
+            x1 = Column(Integer)
+            y1 = Column(Integer)
+            x2 = Column(Integer)
+            y2 = Column(Integer)
+
+            start = composite(Point, x1, y1)
+            end = composite(Point, x2, y2)
+
+        self.assert_compile(
+            select(Vertex),
+            "SELECT vertices.id, vertices.x1, vertices.y1, vertices.x2, "
+            "vertices.y2 FROM vertices",
+        )
+
 
 class NestedTest(fixtures.MappedTest, testing.AssertsCompiledSQL):
     @classmethod