Skip to content

Commit a964956

Browse files
authored
Allow snapshot cursors from other collections for collection group queries. (#8882)
Closes #8633. Supersedes #8810.
1 parent 1a4bd76 commit a964956

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

firestore/google/cloud/firestore_v1/query.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,19 @@ def offset(self, num_to_skip):
390390
all_descendants=self._all_descendants,
391391
)
392392

393+
def _check_snapshot(self, document_fields):
394+
"""Validate local snapshots for non-collection-group queries.
395+
396+
Raises:
397+
ValueError: for non-collection-group queries, if the snapshot
398+
is from a different collection.
399+
"""
400+
if self._all_descendants:
401+
return
402+
403+
if document_fields.reference._path[:-1] != self._parent._path:
404+
raise ValueError("Cannot use snapshot from another collection as a cursor.")
405+
393406
def _cursor_helper(self, document_fields, before, start):
394407
"""Set values to be used for a ``start_at`` or ``end_at`` cursor.
395408
@@ -419,10 +432,7 @@ def _cursor_helper(self, document_fields, before, start):
419432
if isinstance(document_fields, tuple):
420433
document_fields = list(document_fields)
421434
elif isinstance(document_fields, document.DocumentSnapshot):
422-
if document_fields.reference._path[:-1] != self._parent._path:
423-
raise ValueError(
424-
"Cannot use snapshot from another collection as a cursor."
425-
)
435+
self._check_snapshot(document_fields)
426436
else:
427437
# NOTE: We copy so that the caller can't modify after calling.
428438
document_fields = copy.deepcopy(document_fields)

firestore/tests/unit/v1/test_query.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,28 @@ def test__cursor_helper_w_snapshot_wrong_collection(self):
459459
with self.assertRaises(ValueError):
460460
query._cursor_helper(snapshot, False, False)
461461

462+
def test__cursor_helper_w_snapshot_other_collection_all_descendants(self):
463+
values = {"a": 7, "b": "foo"}
464+
docref = self._make_docref("there", "doc_id")
465+
snapshot = self._make_snapshot(docref, values)
466+
collection = self._make_collection("here")
467+
query1 = self._make_one(collection, all_descendants=True)
468+
469+
query2 = query1._cursor_helper(snapshot, False, False)
470+
471+
self.assertIs(query2._parent, collection)
472+
self.assertIsNone(query2._projection)
473+
self.assertEqual(query2._field_filters, ())
474+
self.assertEqual(query2._orders, ())
475+
self.assertIsNone(query2._limit)
476+
self.assertIsNone(query2._offset)
477+
self.assertIsNone(query2._start_at)
478+
479+
cursor, before = query2._end_at
480+
481+
self.assertIs(cursor, snapshot)
482+
self.assertFalse(before)
483+
462484
def test__cursor_helper_w_snapshot(self):
463485
values = {"a": 7, "b": "foo"}
464486
docref = self._make_docref("here", "doc_id")

0 commit comments

Comments
 (0)