diff --git a/docs/changelog.rst b/docs/changelog.rst index d543b169..819f4e0b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,7 +6,8 @@ Changelog Development =========== - (Fill this out as you fix issues and develop your features). -- Fixed a bug that made the queryset drop the read_preference after clone(). +- Fix a bug that made the queryset drop the read_preference after clone(). +- Fix the behavior of Doc.objects.limit(0) which should return all documents (similar to mongodb) #2311 Changes in 0.20.0 ================= diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index 875cbfda..6ad08617 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -83,7 +83,7 @@ class BaseQuerySet: self._cursor_obj = None self._limit = None self._skip = None - self._empty = False + self._hint = -1 # Using -1 as None is a valid value for hint self._collation = None self._batch_size = None @@ -91,6 +91,13 @@ class BaseQuerySet: self._max_time_ms = None self._comment = None + # Hack - As people expect cursor[5:5] to return + # an empty result set. It's hard to do that right, though, because the + # server uses limit(0) to mean 'no limit'. So we set _empty + # in that case and check for it when iterating. We also unset + # it anytime we change _limit. Inspired by how it is done in pymongo.Cursor + self._empty = False + def __call__(self, q_obj=None, **query): """Filter the selected documents by calling the :class:`~mongoengine.queryset.QuerySet` with a query. diff --git a/tests/queryset/test_queryset.py b/tests/queryset/test_queryset.py index 36da5d74..73c419b3 100644 --- a/tests/queryset/test_queryset.py +++ b/tests/queryset/test_queryset.py @@ -409,6 +409,9 @@ class TestQueryset(unittest.TestCase): assert list(A.objects.none()) == [] assert list(A.objects.none().all()) == [] + assert list(A.objects.none().limit(1)) == [] + assert list(A.objects.none().skip(1)) == [] + assert list(A.objects.none()[:5]) == [] def test_chaining(self): class A(Document):