Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fde9b59

Browse files
mcdonctseaver
authored andcommitted
Do not pass 'offset' once the query iterator has a cursor (googleapis#5503)
Closes googleapis#4675.
1 parent 16c3929 commit fde9b59

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

datastore/google/cloud/datastore/query.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,12 @@ def _build_protobuf(self):
452452
if self.max_results is not None:
453453
pb.limit.value = self.max_results - self.num_results
454454

455-
if self._offset is not None:
456-
# NOTE: The offset goes down relative to the location
457-
# because we are updating the cursor each time.
458-
pb.offset = self._offset - self._skipped_results
455+
if start_cursor is None and self._offset is not None:
456+
# NOTE: We don't need to add an offset to the request protobuf
457+
# if we are using an existing cursor, because the offset
458+
# is only relative to the start of the result set, not
459+
# relative to each page (this method is called per-page)
460+
pb.offset = self._offset
459461

460462
return pb
461463

datastore/tests/system/test_system.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,18 @@ def test_query_paginate_simple_timestamp_keys(self):
397397

398398
self.assertTrue(page_count > 1)
399399

400+
def test_query_offset_timestamp_keys(self):
401+
# See issue #4675
402+
max_all = 10000
403+
offset = 1
404+
max_offset = max_all - offset
405+
query = self.CLIENT.query(kind='timestamp_key')
406+
all_w_limit = list(query.fetch(limit=max_all))
407+
self.assertEqual(len(all_w_limit), max_all)
408+
409+
offset_w_limit = list(query.fetch(offset=offset, limit=max_offset))
410+
self.assertEqual(offset_w_limit, all_w_limit[offset:])
411+
400412
def test_query_paginate_with_offset(self):
401413
page_query = self._base_query()
402414
page_query.order = 'appearances'

datastore/tests/unit/test_query.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,21 +404,27 @@ def test__build_protobuf_empty(self):
404404
expected_pb = query_pb2.Query()
405405
self.assertEqual(pb, expected_pb)
406406

407-
def test__build_protobuf_all_values(self):
407+
def test__build_protobuf_all_values_except_offset(self):
408+
# this test and the following (all_values_except_start_and_end_cursor)
409+
# test mutually exclusive states; the offset is ignored
410+
# if a start_cursor is supplied
408411
from google.cloud.datastore_v1.proto import query_pb2
409412
from google.cloud.datastore.query import Query
410413

411414
client = _Client(None)
412415
query = Query(client)
413416
limit = 15
414-
offset = 9
415417
start_bytes = b'i\xb7\x1d'
416418
start_cursor = 'abcd'
417419
end_bytes = b'\xc3\x1c\xb3'
418420
end_cursor = 'wxyz'
419421
iterator = self._make_one(
420-
query, client, limit=limit, offset=offset,
421-
start_cursor=start_cursor, end_cursor=end_cursor)
422+
query,
423+
client,
424+
limit=limit,
425+
start_cursor=start_cursor,
426+
end_cursor=end_cursor
427+
)
422428
self.assertEqual(iterator.max_results, limit)
423429
iterator.num_results = 4
424430
iterator._skipped_results = 1
@@ -427,6 +433,32 @@ def test__build_protobuf_all_values(self):
427433
expected_pb = query_pb2.Query(
428434
start_cursor=start_bytes,
429435
end_cursor=end_bytes,
436+
)
437+
expected_pb.limit.value = limit - iterator.num_results
438+
self.assertEqual(pb, expected_pb)
439+
440+
def test__build_protobuf_all_values_except_start_and_end_cursor(self):
441+
# this test and the previous (all_values_except_start_offset)
442+
# test mutually exclusive states; the offset is ignored
443+
# if a start_cursor is supplied
444+
from google.cloud.datastore_v1.proto import query_pb2
445+
from google.cloud.datastore.query import Query
446+
447+
client = _Client(None)
448+
query = Query(client)
449+
limit = 15
450+
offset = 9
451+
iterator = self._make_one(
452+
query,
453+
client,
454+
limit=limit,
455+
offset=offset,
456+
)
457+
self.assertEqual(iterator.max_results, limit)
458+
iterator.num_results = 4
459+
460+
pb = iterator._build_protobuf()
461+
expected_pb = query_pb2.Query(
430462
offset=offset - iterator._skipped_results,
431463
)
432464
expected_pb.limit.value = limit - iterator.num_results

0 commit comments

Comments
 (0)