From eb8a39c58cf3ef8f43d9bead3a534b5700f4a519 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 29 Aug 2014 14:01:38 -0400 Subject: - The :class:`.Query` will raise an exception when :meth:`.Query.yield_per` is used with mappings or options where eager loading, either joined or subquery, would take place. These loading strategies are not currently compatible with yield_per, so by raising this error, the method is safer to use - combine with sending False to :meth:`.Query.enable_eagerloads` to disable the eager loaders. --- lib/sqlalchemy/orm/query.py | 19 ++++++++++++++++--- lib/sqlalchemy/orm/strategies.py | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'lib/sqlalchemy') diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index a3711db6a..372eba0fe 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -595,11 +595,18 @@ class Query(object): This is used primarily when nesting the Query's statement into a subquery or other - selectable. + selectable, or when using :meth:`.Query.yield_per`. """ self._enable_eagerloads = value + def _no_yield_per(self, message): + raise sa_exc.InvalidRequestError( + "The yield_per Query option is currently not " + "compatible with %s eager loading. Please " + "specify query.enable_eagerloads(False) in order to " + "proceed with query.yield_per()." % message) + @_generative() def with_labels(self): """Apply column labels to the return value of Query.statement. @@ -714,9 +721,11 @@ class Query(object): (e.g. approximately 1000) is used, even with DBAPIs that buffer rows (which are most). - The :meth:`.yield_per` method **is not compatible with most + The :meth:`.Query.yield_per` method **is not compatible with most eager loading schemes, including joinedload and subqueryload**. - See the warning below. + For this reason it typically should be combined with the use of + the :meth:`.Query.enable_eagerloads` method, passing a value of + False. See the warning below. .. warning:: @@ -744,6 +753,10 @@ class Query(object): than that of an ORM-mapped object, but should still be taken into consideration when benchmarking. + .. seealso:: + + :meth:`.Query.enable_eagerloads` + """ self._yield_per = count self._execution_options = self._execution_options.union( diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 29cb67583..de3d0dcef 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -712,6 +712,8 @@ class SubqueryLoader(AbstractRelationshipLoader): if not context.query._enable_eagerloads: return + elif context.query._yield_per: + context.query._no_yield_per("subquery") path = path[self.parent_property] @@ -1087,6 +1089,8 @@ class JoinedLoader(AbstractRelationshipLoader): if not context.query._enable_eagerloads: return + elif context.query._yield_per: + context.query._no_yield_per("joined") path = path[self.parent_property] -- cgit v1.2.1