]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
handle non-mapped mixins for with_loader_criteria reduce
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 9 Jun 2022 12:55:14 +0000 (08:55 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 9 Jun 2022 12:55:14 +0000 (08:55 -0400)
special handling is needed for a with_loader_criteria()
against a non-mapped mixin class.  added that to test
coverage

Fixes: #8109
Change-Id: Ia599361c8faab008e92095eb4607d02820f590d5

lib/sqlalchemy/orm/util.py
lib/sqlalchemy/testing/pickleable.py
test/orm/test_pickled.py

index 14a6bccb01e1133d4e56ba29e5e0cea7543f3c25..0d4d4a8372db81aac0c6f1809adc3edab3c229b1 100644 (file)
@@ -1256,7 +1256,7 @@ class LoaderCriteriaOption(CriteriaOption):
         return (
             LoaderCriteriaOption._unreduce,
             (
-                self.entity.class_ if self.entity else None,
+                self.entity.class_ if self.entity else self.root_entity,
                 self._where_crit_orig,
                 self.include_aliases,
                 self.propagate_to_loaders,
index c14c681f67e1dd1d557502c4921c3787ec4b1d13..4206e3041d9bb1359aee4dd96d2357b5b9be8613 100644 (file)
@@ -14,6 +14,8 @@ unpickling.
 from __future__ import annotations
 
 from . import fixtures
+from ..schema import Column
+from ..types import String
 
 
 class User(fixtures.ComparableEntity):
@@ -55,6 +57,14 @@ class Screen:
         self.parent = parent
 
 
+class Mixin:
+    email_address = Column(String)
+
+
+class AddressWMixin(Mixin, fixtures.ComparableEntity):
+    pass
+
+
 class Foo:
     def __init__(self, moredata, stuff="im stuff"):
         self.data = "im data"
index fa3fbfa2ca707ce42acad1b5ee7e72abb97b692f..a0706a1337242fff6fe8dbaabc97e5fff8920544 100644 (file)
@@ -24,10 +24,12 @@ from sqlalchemy.testing import eq_
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing.fixtures import fixture_session
 from sqlalchemy.testing.pickleable import Address
+from sqlalchemy.testing.pickleable import AddressWMixin
 from sqlalchemy.testing.pickleable import Child1
 from sqlalchemy.testing.pickleable import Child2
 from sqlalchemy.testing.pickleable import Dingaling
 from sqlalchemy.testing.pickleable import EmailUser
+from sqlalchemy.testing.pickleable import Mixin
 from sqlalchemy.testing.pickleable import Order
 from sqlalchemy.testing.pickleable import Parent
 from sqlalchemy.testing.pickleable import Screen
@@ -328,23 +330,27 @@ class PickleTest(fixtures.MappedTest):
         eq_(len(u2.addresses), 2)
 
     @testing.combinations(True, False, argnames="pickle_it")
-    def test_loader_criteria(self, pickle_it):
+    @testing.combinations(True, False, argnames="use_mixin")
+    def test_loader_criteria(self, pickle_it, use_mixin):
         """test #8109"""
 
         users, addresses = (self.tables.users, self.tables.addresses)
 
+        AddressCls = AddressWMixin if use_mixin else Address
+
         self.mapper_registry.map_imperatively(
             User,
             users,
-            properties={"addresses": relationship(Address)},
+            properties={"addresses": relationship(AddressCls)},
         )
-        self.mapper_registry.map_imperatively(Address, addresses)
+
+        self.mapper_registry.map_imperatively(AddressCls, addresses)
 
         with fixture_session(expire_on_commit=False) as sess:
             u1 = User(name="ed")
             u1.addresses = [
-                Address(email_address="ed@bar.com"),
-                Address(email_address="ed@foo.com"),
+                AddressCls(email_address="ed@bar.com"),
+                AddressCls(email_address="ed@foo.com"),
             ]
             sess.add(u1)
             sess.commit()
@@ -353,8 +359,9 @@ class PickleTest(fixtures.MappedTest):
             # note that non-lambda is not picklable right now as
             # SQL expressions usually can't be pickled.
             opt = with_loader_criteria(
-                Address,
+                Mixin if use_mixin else Address,
                 no_ed_foo,
+                include_aliases=True,
             )
 
             u1 = sess.query(User).options(opt).first()