summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/ext
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2018-08-27 11:07:48 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2018-08-27 14:59:08 -0400
commitb601051b217c435934cd41011c8a47de4c783e09 (patch)
tree8874663e4ad0e9e682a2129f4669da9db3dd6add /lib/sqlalchemy/ext
parent90a772b19339b97517bc46f016122341528e440a (diff)
downloadsqlalchemy-b601051b217c435934cd41011c8a47de4c783e09.tar.gz
Add BakedQuery.to_query() method
Added new feature :meth:`.BakedQuery.to_query`, which allows for a clean way of using one :class:`.BakedQuery` as a subquery inside of another :class:`.BakedQuery` without needing to refer explicitly to a :class:`.Session`. Fixes: #4318 Change-Id: I528056c7d140036c27b95500d7a60dcd14784016
Diffstat (limited to 'lib/sqlalchemy/ext')
-rw-r--r--lib/sqlalchemy/ext/baked.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/sqlalchemy/ext/baked.py b/lib/sqlalchemy/ext/baked.py
index 72fe92957..516879142 100644
--- a/lib/sqlalchemy/ext/baked.py
+++ b/lib/sqlalchemy/ext/baked.py
@@ -15,6 +15,7 @@ compiled result to be fully cached.
from ..orm.query import Query
from ..orm import strategy_options
+from ..orm.session import Session
from ..sql import util as sql_util, func, literal_column
from ..orm import exc as orm_exc
from .. import exc as sa_exc
@@ -232,6 +233,56 @@ class BakedQuery(object):
self._bakery[self._effective_key(session)] = context
return context
+ def to_query(self, query_or_session):
+ """Return the :class:`.Query` object for use as a subquery.
+
+ This method should be used within the lambda callable being used
+ to generate a step of an enclosing :class:`.BakedQuery`. The
+ parameter should normally be the :class:`.Query` object that
+ is passed to the lambda::
+
+ sub_bq = self.bakery(lambda s: s.query(User.name))
+ sub_bq += lambda q: q.filter(
+ User.id == Address.user_id).correlate(Address)
+
+ main_bq = self.bakery(lambda s: s.query(Address))
+ main_bq += lambda q: q.filter(
+ sub_bq.to_query(q).exists())
+
+ In the case where the subquery is used in the first callable against
+ a :class:`.Session`, the :class:`.Session` is also accepted::
+
+ sub_bq = self.bakery(lambda s: s.query(User.name))
+ sub_bq += lambda q: q.filter(
+ User.id == Address.user_id).correlate(Address)
+
+ main_bq = self.bakery(
+ lambda s: s.query(Address.id, sub_bq.to_query(q).as_scalar())
+ )
+
+ :param query_or_session: a :class:`.Query` object or a class
+ :class:`.Session` object, that is assumed to be within the context
+ of an enclosing :class:`.BakedQuery` callable.
+
+
+ .. versionadded:: 1.3
+
+
+ """
+
+ if isinstance(query_or_session, Session):
+ session = query_or_session
+ elif isinstance(query_or_session, Query):
+ session = query_or_session.session
+ if session is None:
+ raise sa_exc.ArgumentError(
+ "Given Query needs to be associated with a Session")
+ else:
+ raise TypeError(
+ "Query or Session object expected, got %r." %
+ type(query_or_session))
+ return self._as_query(session)
+
def _as_query(self, session):
query = self.steps[0](session)