summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-05-13 19:55:49 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-05-13 19:55:49 +0000
commit17684a1b81b63a436fcf4f8426bcd822bdb8d463 (patch)
treedf476f202c006b5b08ee62a27b2b1cff462c14bf /lib/sqlalchemy/orm
parent1b6306c69e730eafdae499443efeb83322ce03e8 (diff)
downloadsqlalchemy-17684a1b81b63a436fcf4f8426bcd822bdb8d463.tar.gz
- LIMIT/OFFSET of zero is detected within compiler and is counted
- Query.__getitem__ now returns list/scalar in all cases, not generative (#1035) - added Query.slice_() which provides the simple "limit/offset from a positive range" operation, we can rename this to range_()/section()/_something_private_because_users_shouldnt_do_this() as needed
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/query.py63
1 files changed, 38 insertions, 25 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index ec3b6344b..b7d6199b8 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -258,7 +258,7 @@ class Query(object):
return equivs
def __no_criterion_condition(self, meth):
- if self._criterion or self._statement or self._from_obj or self._limit or self._offset or self._group_by or self._order_by:
+ if self._criterion or self._statement or self._from_obj or self._limit is not None or self._offset is not None or self._group_by or self._order_by:
raise sa_exc.InvalidRequestError("Query.%s() being called on a Query with existing criterion. " % meth)
self._statement = self._criterion = self._from_obj = None
@@ -276,7 +276,7 @@ class Query(object):
"statement - can't apply criterion.") % meth)
def __no_limit_offset(self, meth):
- if self._limit or self._offset:
+ if self._limit is not None or self._offset is not None:
# TODO: do we want from_self() to be implicit here ? i vote explicit for the time being
raise sa_exc.InvalidRequestError("Query.%s() being called on a Query which already has LIMIT or OFFSET applied. "
"To filter/join to the row-limited results of the query, call from_self() first."
@@ -951,43 +951,50 @@ class Query(object):
def __getitem__(self, item):
if isinstance(item, slice):
- start = item.start
- stop = item.stop
+ start, stop, step = util.decode_slice(item)
# if we slice from the end we need to execute the query
- if (isinstance(start, int) and start < 0) or \
- (isinstance(stop, int) and stop < 0):
+ if start < 0 or stop < 0:
return list(self)[item]
else:
- res = self._clone()
- if start is not None and stop is not None:
- res._offset = (self._offset or 0) + start
- res._limit = stop - start
- elif start is None and stop is not None:
- res._limit = stop
- elif start is not None and stop is None:
- res._offset = (self._offset or 0) + start
- if item.step is not None:
+ res = self.slice_(start, stop)
+ if step is not None:
return list(res)[None:None:item.step]
else:
- return res
+ return list(res)
else:
return list(self[item:item+1])[0]
-
+
+ def slice_(self, start, stop):
+ """apply LIMIT/OFFSET to the ``Query`` based on a range and return the newly resulting ``Query``."""
+
+ if start is not None and stop is not None:
+ self._offset = (self._offset or 0) + start
+ self._limit = stop - start
+ elif start is None and stop is not None:
+ self._limit = stop
+ elif start is not None and stop is None:
+ self._offset = (self._offset or 0) + start
+ slice_ = _generative(__no_statement_condition)(slice_)
+
def limit(self, limit):
"""Apply a ``LIMIT`` to the query and return the newly resulting
``Query``.
"""
- return self[:limit]
-
+
+ self._limit = limit
+ limit = _generative(__no_statement_condition)(limit)
+
def offset(self, offset):
"""Apply an ``OFFSET`` to the query and return the newly resulting
``Query``.
"""
- return self[offset:]
-
+
+ self._offset = offset
+ offset = _generative(__no_statement_condition)(offset)
+
def distinct(self):
"""Apply a ``DISTINCT`` to the query and return the newly resulting
``Query``.
@@ -1028,11 +1035,14 @@ class Query(object):
This results in an execution of the underlying query.
"""
- ret = list(self[0:1])
- if len(ret) > 0:
- return ret[0]
+ if self._statement:
+ return list(self)[0]
else:
- return None
+ ret = list(self[0:1])
+ if len(ret) > 0:
+ return ret[0]
+ else:
+ return None
def one(self):
"""Return the first result, raising an exception unless exactly one row exists.
@@ -1040,6 +1050,9 @@ class Query(object):
This results in an execution of the underlying query.
"""
+ if self._statement:
+ raise exceptions.InvalidRequestError("one() not available when from_statement() is used; use `first()` instead.")
+
ret = list(self[0:2])
if len(ret) == 1: