]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
ensure with poly entities are also reconstituted for GC'ed AC
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 26 Jun 2021 20:40:09 +0000 (16:40 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 26 Jun 2021 20:41:31 +0000 (16:41 -0400)
Fixed regression in ORM regarding an internal reconstitution step for the
func:`_orm.with_polymorphic` construct, when the user-facing object is
garbage collected as the query is processed. The reconstitution was not
ensuring the sub-entities for the "polymorphic" case were handled, leading
to an ``AttributeError``.

Fixes: #6680
Change-Id: Id35b16d0f2aadb50b5a7385a21fa81b9d8a8325f

doc/build/changelog/unreleased_14/6680.rst [new file with mode: 0644]
lib/sqlalchemy/orm/util.py
test/orm/inheritance/test_with_poly.py

diff --git a/doc/build/changelog/unreleased_14/6680.rst b/doc/build/changelog/unreleased_14/6680.rst
new file mode 100644 (file)
index 0000000..c433ed6
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: bug, regression, orm
+    :tickets: 6680
+
+    Fixed regression in ORM regarding an internal reconstitution step for the
+    func:`_orm.with_polymorphic` construct, when the user-facing object is
+    garbage collected as the query is processed. The reconstitution was not
+    ensuring the sub-entities for the "polymorphic" case were handled, leading
+    to an ``AttributeError``.
index 856afabb0f61d22a9c2aec896c5d944344a4bdae..15f584c1ffbdd97258dad393c72ef6dacfdbd3dd 100644 (file)
@@ -524,6 +524,15 @@ class AliasedClass(object):
         obj = cls.__new__(cls)
         obj.__name__ = "AliasedClass_%s" % aliased_insp.mapper.class_.__name__
         obj._aliased_insp = aliased_insp
+
+        if aliased_insp._is_with_polymorphic:
+            for sub_aliased_insp in aliased_insp._with_polymorphic_entities:
+                if sub_aliased_insp is not aliased_insp:
+                    ent = AliasedClass._reconstitute_from_aliased_insp(
+                        sub_aliased_insp
+                    )
+                    setattr(obj, sub_aliased_insp.class_.__name__, ent)
+
         return obj
 
     def __getattr__(self, key):
index 2492e593c8d8635e79056d9c1817cdedfe2d4b2f..264e3ae3f0d49e316c9d00fcf98765851f693869 100644 (file)
@@ -1,6 +1,7 @@
 from sqlalchemy import and_
 from sqlalchemy import exc
 from sqlalchemy import or_
+from sqlalchemy import select
 from sqlalchemy import testing
 from sqlalchemy.orm import with_polymorphic
 from sqlalchemy.testing import eq_
@@ -50,9 +51,14 @@ class _WithPolymorphicBase(_PolymorphicFixtureBase):
 
         self.assert_sql_count(testing.db, go, 1)
 
-    def test_col_expression_base_plus_two_subs(self):
+    @testing.combinations((True,), (False,), argnames="use_star")
+    def test_col_expression_base_plus_two_subs(self, use_star):
         sess = fixture_session()
-        pa = with_polymorphic(Person, [Engineer, Manager])
+
+        if use_star:
+            pa = with_polymorphic(Person, "*")
+        else:
+            pa = with_polymorphic(Person, [Engineer, Manager])
 
         eq_(
             sess.query(
@@ -69,6 +75,14 @@ class _WithPolymorphicBase(_PolymorphicFixtureBase):
             [("dilbert", "java", None), ("dogbert", None, "dogbert")],
         )
 
+    def test_orm_entity_w_gc(self):
+        """test #6680"""
+        sess = fixture_session()
+
+        stmt = select(with_polymorphic(Person, "*"))
+
+        eq_(len(sess.execute(stmt).all()), 5)
+
     def test_join_to_join_entities(self):
         sess = fixture_session()
         pa = with_polymorphic(Person, [Engineer])