]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- fixed bug where eagerload() (nor lazyload()) option didn't properly
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 31 Oct 2006 20:40:22 +0000 (20:40 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 31 Oct 2006 20:40:22 +0000 (20:40 +0000)
instruct the Query whether or not to use "nesting" when producing a
LIMIT query.

CHANGES
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/query.py
lib/sqlalchemy/orm/strategies.py
test/orm/mapper.py

diff --git a/CHANGES b/CHANGES
index a6021ca927f46bf4f7987613b24783398d8e0cbc..f1cdb1e011a5564a878c67ee3d19205ccbd6af50 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,9 @@ passive_deletes=True on a relation().
 - further fixes to sqlite booleans, weren't working as defaults
 - fix to postgres sequence quoting when using schemas
 - fixed direct execution of Compiled objects
+- fixed bug where eagerload() (nor lazyload()) option didn't properly
+instruct the Query whether or not to use "nesting" when producing a
+LIMIT query.
 
 0.3.0
 - General:
index 4fcc7d14c7b20e1ba97a0ee658ff33b7025df6b7..abfe18db351a097e44951fa3a26d1f7fd1495384 100644 (file)
@@ -160,6 +160,7 @@ class Mapper(object):
         # "polymorphic identity" of the row, which indicates which Mapper should be used
         # to construct a new object instance from that row.
         self.polymorphic_on = polymorphic_on
+        self._eager_loaders = util.Set()
         
         # our 'polymorphic identity', a string name that when located in a result set row
         # indicates this Mapper should be used to construct the object instance for that row.
@@ -711,7 +712,7 @@ class Mapper(object):
     
     def has_eager(self):
         """return True if one of the properties attached to this Mapper is eager loading"""
-        return getattr(self, '_has_eager', False)
+        return len(self._eager_loaders) > 0
     
     def instances(self, cursor, session, *mappers, **kwargs):
         """return a list of mapped instances corresponding to the rows in a given ResultProxy."""
index a2c6624821e50514f3d61a4dc5e5a53407b3bdf0..9c76c6a176550247e436f8f40e041ef9daa01ee6 100644 (file)
@@ -374,7 +374,7 @@ class Query(object):
         generated query as a subquery inside of a larger eager-loading query.  this is used
         with keywords like distinct, limit and offset and the mapper defines eager loads."""
         return (
-            self.mapper.has_eager()
+            len(querycontext.eager_loaders) > 0
             and self._nestable(**querycontext.select_args())
         )
 
@@ -473,6 +473,7 @@ class QueryContext(OperationContext):
         self.distinct = kwargs.pop('distinct', False)
         self.limit = kwargs.pop('limit', None)
         self.offset = kwargs.pop('offset', None)
+        self.eager_loaders = util.Set([x for x in query.mapper._eager_loaders])
         self.statement = None
         super(QueryContext, self).__init__(query.mapper, query.with_options, **kwargs)
     def select_args(self):
index bfcc377c05fd413236580271e8f194625e625d81..6e5590bb00ae43ac7522e2735ba0ec79bcb4b7f0 100644 (file)
@@ -289,7 +289,7 @@ class EagerLoader(AbstractRelationLoader):
         super(EagerLoader, self).init()
         if self.parent.isa(self.mapper):
             raise exceptions.ArgumentError("Error creating eager relationship '%s' on parent class '%s' to child class '%s': Cant use eager loading on a self referential relationship." % (self.key, repr(self.parent.class_), repr(self.mapper.class_)))
-        self.parent._has_eager = True
+        self.parent._eager_loaders.add(self.parent_property)
 
         self.clauses = {}
         self.clauses_by_lead_mapper = {}
@@ -518,6 +518,13 @@ class EagerLazyOption(StrategizedOption):
     def __init__(self, key, lazy=True):
         super(EagerLazyOption, self).__init__(key)
         self.lazy = lazy
+    def process_query_property(self, context, prop):
+        if self.lazy:
+            if prop in context.eager_loaders:
+                context.eager_loaders.remove(prop)
+        else:
+            context.eager_loaders.add(prop)
+        super(EagerLazyOption, self).process_query_property(context, prop)
     def get_strategy_class(self):
         if self.lazy:
             return LazyLoader
index 6c54a5bfbeb86461ecbf7f9dcb052be88cb140f2..3a56ff661919bab2e6fb1903ccfca1f69ac6b64c 100644 (file)
@@ -382,6 +382,30 @@ class MapperTest(MapperSuperTest):
             self.assert_result(l, User, *user_address_result)
         self.assert_sql_count(db, go, 0)
 
+    def testeageroptionswithlimit(self):
+        sess = create_session()
+        mapper(User, users, properties = dict(
+            addresses = relation(mapper(Address, addresses), lazy = True)
+        ))
+        u = sess.query(User).options(eagerload('addresses')).get_by(user_id=8)
+
+        def go():
+            assert u.user_id == 8
+            assert len(u.addresses) == 3
+        self.assert_sql_count(db, go, 0)
+
+    def testlazyoptionswithlimit(self):
+        sess = create_session()
+        mapper(User, users, properties = dict(
+            addresses = relation(mapper(Address, addresses), lazy = False)
+        ))
+        u = sess.query(User).options(lazyload('addresses')).get_by(user_id=8)
+
+        def go():
+            assert u.user_id == 8
+            assert len(u.addresses) == 3
+        self.assert_sql_count(db, go, 1)
+
     def testeagerdegrade(self):
         """tests that an eager relation automatically degrades to a lazy relation if eager columns are not available"""
         sess = create_session()