Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cassandra/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -2965,7 +2965,9 @@ def start_fetching_next_page(self):

.. versionadded:: 2.0.0
"""
log.debug('Pagination: Fetching next page')
if not self._paging_state:
log.debug('Pagination: No more pages to fetch')
raise QueryExhausted()

self._make_query_plan()
Expand Down
39 changes: 26 additions & 13 deletions cassandra/cqlengine/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ def __init__(self, model):
# results cache
self._result_cache = None
self._result_idx = None
self._result_generator = None

self._count = None
self._batch = None
self._ttl = getattr(model, '__default_ttl__', None)
self._consistency = None
Expand Down Expand Up @@ -308,7 +310,7 @@ def __deepcopy__(self, memo):

def __len__(self):
self._execute_query()
return len(self._result_cache)
return self.count()

# ----query generation / execution----

Expand Down Expand Up @@ -340,7 +342,8 @@ def _execute_query(self):
if self._batch:
raise CQLEngineException("Only inserts, updates, and deletes are available in batch mode")
if self._result_cache is None:
self._result_cache = list(self._execute(self._select_query()))
self._result_generator = (i for i in self._execute(self._select_query()))
self._result_cache = []
self._construct_result = self._get_result_constructor()

def _fill_result_cache_to_idx(self, idx):
Expand All @@ -354,21 +357,32 @@ def _fill_result_cache_to_idx(self, idx):
else:
for idx in range(qty):
self._result_idx += 1
self._result_cache[self._result_idx] = self._construct_result(self._result_cache[self._result_idx])
while True:
try:
self._result_cache[self._result_idx] = self._construct_result(self._result_cache[self._result_idx])
break
except IndexError:
self._result_cache.append(next(self._result_generator))

def __iter__(self):
self._execute_query()

for idx in range(len(self._result_cache)):
instance = self._result_cache[idx]
for idx in range(self.count()):
while True:
try:
instance = self._result_cache[idx]
break
except IndexError:
self._result_cache.append(next(self._result_generator))

if isinstance(instance, dict):
self._fill_result_cache_to_idx(idx)
yield self._result_cache[idx]

def __getitem__(self, s):
self._execute_query()

num_results = len(self._result_cache)
num_results = self.count()

if isinstance(s, slice):
# calculate the amount of results that need to be loaded
Expand Down Expand Up @@ -577,10 +591,10 @@ def get(self, *args, **kwargs):
return self.filter(*args, **kwargs).get()

self._execute_query()
if len(self._result_cache) == 0:
if self.count() == 0:
raise self.model.DoesNotExist
elif len(self._result_cache) > 1:
raise self.model.MultipleObjectsReturned('{0} objects found'.format(len(self._result_cache)))
elif self.count() > 1:
raise self.model.MultipleObjectsReturned('{0} objects found'.format(self.count()))
else:
return self[0]

Expand Down Expand Up @@ -641,13 +655,12 @@ def count(self):
if self._batch:
raise CQLEngineException("Only inserts, updates, and deletes are available in batch mode")

if self._result_cache is None:
if self._count is None:
query = self._select_query()
query.count = True
result = self._execute(query)
return result[0]['count']
else:
return len(self._result_cache)
self._count = result[0]['count']
return self._count

def limit(self, v):
"""
Expand Down