Skip to content

Commit fd21c0c

Browse files
authored
query value max bug fix (Azure#27888)
* Update endpoint_component.py * Update endpoint_component.py * Update CHANGELOG.md * Update test_query.py * Update test_query.py
1 parent d039643 commit fd21c0c

File tree

4 files changed

+59
-22
lines changed

4 files changed

+59
-22
lines changed

sdk/cosmos/azure-cosmos/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#### Breaking Changes
88

99
#### Bugs Fixed
10-
10+
- Bug fix to address queries with VALUE MAX (or any other aggregate) that run into an issue if the query is executed on a container with at least one "empty" partition.
1111
#### Other Changes
1212

1313
### 4.3.1b1 (2022-09-19)

sdk/cosmos/azure-cosmos/azure/cosmos/_execution_context/aio/endpoint_component.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ async def __anext__(self):
180180
for item in res: #TODO check on this being an async loop
181181
for operator in self._local_aggregators:
182182
if isinstance(item, dict) and item:
183-
operator.aggregate(item["item"])
183+
try:
184+
operator.aggregate(item["item"])
185+
except KeyError:
186+
pass
184187
elif isinstance(item, numbers.Number):
185188
operator.aggregate(item)
186189
if self._results is None:

sdk/cosmos/azure-cosmos/azure/cosmos/_execution_context/endpoint_component.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,10 @@ def __next__(self):
193193
for item in res:
194194
for operator in self._local_aggregators:
195195
if isinstance(item, dict) and item:
196-
operator.aggregate(item["item"])
196+
try:
197+
operator.aggregate(item["item"])
198+
except KeyError:
199+
pass
197200
elif isinstance(item, numbers.Number):
198201
operator.aggregate(item)
199202
if self._results is None:

sdk/cosmos/azure-cosmos/test/test_query.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
pytestmark = pytest.mark.cosmosEmulator
1515

16+
1617
@pytest.mark.usefixtures("teardown")
1718
class QueryTest(unittest.TestCase):
1819
"""Test to ensure escaping of non-ascii characters from partition key"""
@@ -62,7 +63,8 @@ def query_change_feed(self, use_partition_key):
6263
# The test targets partition #3
6364
partition_key = "pk"
6465
partition_key_range_id = 0
65-
partitionParam = {"partition_key": partition_key} if use_partition_key else {"partition_key_range_id": partition_key_range_id}
66+
partitionParam = {"partition_key": partition_key} if use_partition_key else {
67+
"partition_key_range_id": partition_key_range_id}
6668

6769
# Read change feed without passing any options
6870
query_iterable = created_collection.query_items_change_feed()
@@ -167,7 +169,8 @@ def query_change_feed(self, use_partition_key):
167169
self.assertEqual(len(iter_list), 0)
168170

169171
def test_populate_query_metrics(self):
170-
created_collection = self.created_db.create_container_if_not_exists("query_metrics_test", PartitionKey(path="/pk"))
172+
created_collection = self.created_db.create_container_if_not_exists("query_metrics_test",
173+
PartitionKey(path="/pk"))
171174
doc_id = 'MyId' + str(uuid.uuid4())
172175
document_definition = {'pk': 'pk', 'id': doc_id}
173176
created_collection.create_item(body=document_definition)
@@ -261,7 +264,8 @@ def test_get_query_plan_through_gateway(self):
261264
limit=None,
262265
distinct=_DistinctType.Ordered)
263266

264-
def _validate_query_plan(self, query, container_link, top, order_by, aggregate, select_value, offset, limit, distinct):
267+
def _validate_query_plan(self, query, container_link, top, order_by, aggregate, select_value, offset, limit,
268+
distinct):
265269
query_plan_dict = self.client.client_connection._GetQueryPlanThroughGateway(query, container_link)
266270
query_execution_info = _PartitionedQueryExecutionInfo(query_plan_dict)
267271
self.assertTrue(query_execution_info.has_rewritten_query())
@@ -294,7 +298,8 @@ def test_unsupported_queries(self):
294298
def test_query_with_non_overlapping_pk_ranges(self):
295299
created_collection = self.created_db.create_container_if_not_exists(
296300
self.config.TEST_COLLECTION_MULTI_PARTITION_WITH_CUSTOM_PK_ID, PartitionKey(path="/pk"))
297-
query_iterable = created_collection.query_items("select * from c where c.pk='1' or c.pk='2'", enable_cross_partition_query=True)
301+
query_iterable = created_collection.query_items("select * from c where c.pk='1' or c.pk='2'",
302+
enable_cross_partition_query=True)
298303
self.assertListEqual(list(query_iterable), [])
299304

300305
def test_offset_limit(self):
@@ -341,8 +346,10 @@ def test_distinct(self):
341346
partition_key=PartitionKey(path="/pk", kind="Hash"),
342347
indexing_policy={
343348
"compositeIndexes": [
344-
[{"path": "/" + pk_field, "order": "ascending"}, {"path": "/" + distinct_field, "order": "ascending"}],
345-
[{"path": "/" + distinct_field, "order": "ascending"}, {"path": "/" + pk_field, "order": "ascending"}]
349+
[{"path": "/" + pk_field, "order": "ascending"},
350+
{"path": "/" + distinct_field, "order": "ascending"}],
351+
[{"path": "/" + distinct_field, "order": "ascending"},
352+
{"path": "/" + pk_field, "order": "ascending"}]
346353
]
347354
}
348355
)
@@ -361,49 +368,62 @@ def test_distinct(self):
361368
padded_docs = self._pad_with_none(documents, distinct_field)
362369

363370
self._validate_distinct(created_collection=created_collection,
364-
query='SELECT distinct c.%s from c ORDER BY c.%s' % (distinct_field, distinct_field), # nosec
365-
results=self._get_distinct_docs(self._get_order_by_docs(padded_docs, distinct_field, None), distinct_field, None, True),
371+
query='SELECT distinct c.%s from c ORDER BY c.%s' % (distinct_field, distinct_field),
372+
# nosec
373+
results=self._get_distinct_docs(
374+
self._get_order_by_docs(padded_docs, distinct_field, None), distinct_field, None,
375+
True),
366376
is_select=False,
367377
fields=[distinct_field])
368378

369379
self._validate_distinct(created_collection=created_collection,
370-
query='SELECT distinct c.%s, c.%s from c ORDER BY c.%s, c.%s' % (distinct_field, pk_field, pk_field, distinct_field), # nosec
371-
results=self._get_distinct_docs(self._get_order_by_docs(padded_docs, pk_field, distinct_field), distinct_field, pk_field, True),
380+
query='SELECT distinct c.%s, c.%s from c ORDER BY c.%s, c.%s' % (
381+
distinct_field, pk_field, pk_field, distinct_field), # nosec
382+
results=self._get_distinct_docs(
383+
self._get_order_by_docs(padded_docs, pk_field, distinct_field), distinct_field,
384+
pk_field, True),
372385
is_select=False,
373386
fields=[distinct_field, pk_field])
374387

375388
self._validate_distinct(created_collection=created_collection,
376-
query='SELECT distinct c.%s, c.%s from c ORDER BY c.%s, c.%s' % (distinct_field, pk_field, distinct_field, pk_field), # nosec
377-
results=self._get_distinct_docs(self._get_order_by_docs(padded_docs, distinct_field, pk_field), distinct_field, pk_field, True),
389+
query='SELECT distinct c.%s, c.%s from c ORDER BY c.%s, c.%s' % (
390+
distinct_field, pk_field, distinct_field, pk_field), # nosec
391+
results=self._get_distinct_docs(
392+
self._get_order_by_docs(padded_docs, distinct_field, pk_field), distinct_field,
393+
pk_field, True),
378394
is_select=False,
379395
fields=[distinct_field, pk_field])
380396

381397
self._validate_distinct(created_collection=created_collection,
382-
query='SELECT distinct value c.%s from c ORDER BY c.%s' % (distinct_field, distinct_field), # nosec
383-
results=self._get_distinct_docs(self._get_order_by_docs(padded_docs, distinct_field, None), distinct_field, None, True),
398+
query='SELECT distinct value c.%s from c ORDER BY c.%s' % (
399+
distinct_field, distinct_field), # nosec
400+
results=self._get_distinct_docs(
401+
self._get_order_by_docs(padded_docs, distinct_field, None), distinct_field, None,
402+
True),
384403
is_select=False,
385404
fields=[distinct_field])
386405

387406
self._validate_distinct(created_collection=created_collection, # returns {} and is right number
388-
query='SELECT distinct c.%s from c' % (distinct_field), # nosec
407+
query='SELECT distinct c.%s from c' % (distinct_field), # nosec
389408
results=self._get_distinct_docs(padded_docs, distinct_field, None, False),
390409
is_select=True,
391410
fields=[distinct_field])
392411

393412
self._validate_distinct(created_collection=created_collection,
394-
query='SELECT distinct c.%s, c.%s from c' % (distinct_field, pk_field), # nosec
413+
query='SELECT distinct c.%s, c.%s from c' % (distinct_field, pk_field), # nosec
395414
results=self._get_distinct_docs(padded_docs, distinct_field, pk_field, False),
396415
is_select=True,
397416
fields=[distinct_field, pk_field])
398417

399418
self._validate_distinct(created_collection=created_collection,
400-
query='SELECT distinct value c.%s from c' % (distinct_field), # nosec
419+
query='SELECT distinct value c.%s from c' % (distinct_field), # nosec
401420
results=self._get_distinct_docs(padded_docs, distinct_field, None, True),
402421
is_select=True,
403422
fields=[distinct_field])
404423

405424
self._validate_distinct(created_collection=created_collection,
406-
query='SELECT distinct c.%s from c ORDER BY c.%s' % (different_field, different_field), # nosec
425+
query='SELECT distinct c.%s from c ORDER BY c.%s' % (different_field, different_field),
426+
# nosec
407427
results=[],
408428
is_select=True,
409429
fields=[different_field])
@@ -573,7 +593,8 @@ def test_cross_partition_query_with_continuation_token_fails(self):
573593
with self.assertRaises(ValueError):
574594
pager = query_iterable.by_page("fake_continuation_token")
575595

576-
def _validate_distinct_on_different_types_and_field_orders(self, collection, query, expected_results, get_mock_result):
596+
def _validate_distinct_on_different_types_and_field_orders(self, collection, query, expected_results,
597+
get_mock_result):
577598
self.count = 0
578599
self.get_mock_result = get_mock_result
579600
query_iterable = collection.query_items(query, enable_cross_partition_query=True)
@@ -587,6 +608,16 @@ def _validate_distinct_on_different_types_and_field_orders(self, collection, que
587608
self.assertEqual(results[i], expected_results[i])
588609
self.count = 0
589610

611+
def test_value_max_query(self):
612+
container = self.created_db.create_container_if_not_exists(
613+
self.config.TEST_COLLECTION_MULTI_PARTITION_WITH_CUSTOM_PK_ID, PartitionKey(path="/pk"))
614+
query = "Select value max(c.version) FROM c where c.isComplete = true and c.lookupVersion = @lookupVersion"
615+
query_results = container.query_items(query, parameters=[
616+
{"name": "@lookupVersion", "value": "console_csat"} # cspell:disable-line
617+
], enable_cross_partition_query=True)
618+
619+
self.assertListEqual(list(query_results), [None])
620+
590621
def _MockNextFunction(self):
591622
if self.count < len(self.payloads):
592623
item, result = self.get_mock_result(self.payloads, self.count)

0 commit comments

Comments
 (0)