summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-06-26 16:40:09 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-06-26 16:41:31 -0400
commit4e7438e0acac2f7c9d24c73d36cdcdb74551f903 (patch)
tree6e917ade06fc267786fa6cbf11ba003e2ff1b84c
parent84a68ac8820a2e1043f8317d42c5681c81cbd9d5 (diff)
downloadsqlalchemy-4e7438e0acac2f7c9d24c73d36cdcdb74551f903.tar.gz
ensure with poly entities are also reconstituted for GC'ed AC
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
-rw-r--r--doc/build/changelog/unreleased_14/6680.rst9
-rw-r--r--lib/sqlalchemy/orm/util.py9
-rw-r--r--test/orm/inheritance/test_with_poly.py18
3 files changed, 34 insertions, 2 deletions
diff --git a/doc/build/changelog/unreleased_14/6680.rst b/doc/build/changelog/unreleased_14/6680.rst
new file mode 100644
index 000000000..c433ed610
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/6680.rst
@@ -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``.
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 856afabb0..15f584c1f 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -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):
diff --git a/test/orm/inheritance/test_with_poly.py b/test/orm/inheritance/test_with_poly.py
index 2492e593c..264e3ae3f 100644
--- a/test/orm/inheritance/test_with_poly.py
+++ b/test/orm/inheritance/test_with_poly.py
@@ -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])