Skip to content
Merged
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
9 changes: 7 additions & 2 deletions google/cloud/firestore_v1/base_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"if passed to one of ``start_at()`` / ``start_after()`` / "
"``end_before()`` / ``end_at()`` to define a cursor."
)

_NO_ORDERS_FOR_CURSOR = (
"Attempting to create a cursor with no fields to order on. "
"When defining a cursor with one of ``start_at()`` / ``start_after()`` / "
Expand Down Expand Up @@ -745,7 +746,10 @@ def _normalize_cursor(self, cursor, orders) -> Optional[Tuple[Any, Any]]:
# Transform to list using orders
values = []
data = document_fields
for order_key in order_keys:

# It isn't required that all order by have a cursor.
# However, we need to be sure they are specified in order without gaps
for order_key in order_keys[: len(data)]:
try:
if order_key in data:
values.append(data[order_key])
Expand All @@ -756,9 +760,10 @@ def _normalize_cursor(self, cursor, orders) -> Optional[Tuple[Any, Any]]:
except KeyError:
msg = _MISSING_ORDER_BY.format(order_key, data)
raise ValueError(msg)

document_fields = values

if len(document_fields) != len(orders):
if len(document_fields) > len(orders):
msg = _MISMATCH_CURSOR_W_ORDER_BY.format(document_fields, order_keys)
raise ValueError(msg)

Expand Down
13 changes: 13 additions & 0 deletions tests/unit/v1/test_base_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,19 @@ def test__normalize_cursor_as_dict_mismatched_order(self):
with self.assertRaises(ValueError):
query._normalize_cursor(cursor, query._orders)

def test__normalize_cursor_as_dict_extra_orders_ok(self):
cursor = ({"name": "Springfield"}, True)
query = self._make_one(mock.sentinel.parent).order_by("name").order_by("state")

normalized = query._normalize_cursor(cursor, query._orders)
self.assertEqual(normalized, (["Springfield"], True))

def test__normalize_cursor_extra_orders_ok(self):
cursor = (["Springfield"], True)
query = self._make_one(mock.sentinel.parent).order_by("name").order_by("state")

query._normalize_cursor(cursor, query._orders)

def test__normalize_cursor_w_delete(self):
from google.cloud.firestore_v1 import DELETE_FIELD

Expand Down