diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-09-27 07:08:26 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-09-27 07:08:26 +0000 |
commit | a81bd92d6ebef5053cbb6882b336c50c1134c273 (patch) | |
tree | 6d9df595eedaa29794e7a02122f79cc3cf73b1c9 /lib/sqlalchemy/ext/selectresults.py | |
parent | df9c1a10b568cb89aec41fcb0c7c31a1ae75943c (diff) | |
download | sqlalchemy-a81bd92d6ebef5053cbb6882b336c50c1134c273.tar.gz |
- specifying joins in the from_obj argument of query.select() will
replace the main table of the query, if the table is somewhere within
the given from_obj. this makes it possible to produce custom joins and
outerjoins in queries without the main table getting added twice.
[ticket:315]
- added join_to and outerjoin_to transformative methods to SelectResults,
to build up join/outerjoin conditions based on property names. also
added select_from to explicitly set from_obj parameter.
- factored "results" arrays from the mapper test suite and into the
"tables" mapper
- added "viewonly" param to docs
Diffstat (limited to 'lib/sqlalchemy/ext/selectresults.py')
-rw-r--r-- | lib/sqlalchemy/ext/selectresults.py | 66 |
1 files changed, 60 insertions, 6 deletions
diff --git a/lib/sqlalchemy/ext/selectresults.py b/lib/sqlalchemy/ext/selectresults.py index a35cdfa7e..93698a5e0 100644 --- a/lib/sqlalchemy/ext/selectresults.py +++ b/lib/sqlalchemy/ext/selectresults.py @@ -18,13 +18,14 @@ class SelectResults(object): instance with further limiting criterion added. When interpreted in an iterator context (such as via calling list(selectresults)), executes the query.""" - def __init__(self, query, clause=None, ops={}): + def __init__(self, query, clause=None, ops={}, joinpoint=None): """constructs a new SelectResults using the given Query object and optional WHERE clause. ops is an optional dictionary of bind parameter values.""" self._query = query self._clause = clause self._ops = {} self._ops.update(ops) + self._joinpoint = joinpoint or (self._query.table, self._query.mapper) def count(self): """executes the SQL count() function against the SelectResults criterion.""" @@ -60,7 +61,7 @@ class SelectResults(object): def clone(self): """creates a copy of this SelectResults.""" - return SelectResults(self._query, self._clause, self._ops.copy()) + return SelectResults(self._query, self._clause, self._ops.copy(), self._joinpoint) def filter(self, clause): """applies an additional WHERE clause against the query.""" @@ -68,23 +69,76 @@ class SelectResults(object): new._clause = sql.and_(self._clause, clause) return new + def select(self, clause): + return self.filter(clause) + def order_by(self, order_by): - """applies an ORDER BY to the query.""" + """apply an ORDER BY to the query.""" new = self.clone() new._ops['order_by'] = order_by return new def limit(self, limit): - """applies a LIMIT to the query.""" + """apply a LIMIT to the query.""" return self[:limit] def offset(self, offset): - """applies an OFFSET to the query.""" + """apply an OFFSET to the query.""" return self[offset:] def list(self): - """returns the results represented by this SelectResults as a list. this results in an execution of the underlying query.""" + """return the results represented by this SelectResults as a list. + + this results in an execution of the underlying query.""" return list(self) + + def select_from(self, from_obj): + """set the from_obj parameter of the query to a specific table or set of tables. + + from_obj is a list.""" + new = self.clone() + new._ops['from_obj'] = from_obj + return new + + def join_to(self, prop): + """join the table of this SelectResults to the table located against the given property name. + + subsequent calls to join_to or outerjoin_to will join against the rightmost table located from the + previous join_to or outerjoin_to call, searching for the property starting with the rightmost mapper + last located.""" + new = self.clone() + (clause, mapper) = self._join_to(prop, outerjoin=False) + new._ops['from_obj'] = [clause] + new._joinpoint = (clause, mapper) + return new + + def outerjoin_to(self, prop): + """outer join the table of this SelectResults to the table located against the given property name. + + subsequent calls to join_to or outerjoin_to will join against the rightmost table located from the + previous join_to or outerjoin_to call, searching for the property starting with the rightmost mapper + last located.""" + new = self.clone() + (clause, mapper) = self._join_to(prop, outerjoin=True) + new._ops['from_obj'] = [clause] + new._joinpoint = (clause, mapper) + return new + + def _join_to(self, prop, outerjoin=False): + [keys,p] = self._query._locate_prop(prop, start=self._joinpoint[1]) + clause = self._joinpoint[0] + mapper = self._joinpoint[1] + for key in keys: + prop = mapper.props[key] + if outerjoin: + clause = clause.outerjoin(prop.mapper.mapped_table, prop.get_join()) + else: + clause = clause.join(prop.mapper.mapped_table, prop.get_join()) + mapper = prop.mapper + return (clause, mapper) + + def compile(self): + return self._query.compile(self._clause, **self._ops) def __getitem__(self, item): if isinstance(item, slice): |