Skip to content

Commit 64f9f77

Browse files
committed
fix(issue-search): correctly parse negated contains filters
1 parent 417a017 commit 64f9f77

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

src/sentry/search/events/filter.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,9 +669,19 @@ def convert_search_filter_to_snuba_query(
669669
# together. Otherwise just return the raw condition, so that it can be
670670
# used correctly in aggregates.
671671
if is_null_condition:
672-
return [is_null_condition, condition]
673-
else:
674-
return condition
672+
return [is_null_condition, *_flatten_conditions(condition)]
673+
return condition
674+
675+
676+
def _flatten_conditions(cond: list[Any]) -> list[Any]:
677+
"""
678+
Flatten nested legacy conditions into a flat list. A legacy condition is
679+
[lhs, op_string, rhs]. Wildcard processing can create nested lists that
680+
snuba_sdk.legacy.parse_condition cannot handle.
681+
"""
682+
if len(cond) == 3 and isinstance(cond[1], str):
683+
return [cond]
684+
return [c for item in cond if isinstance(item, list) for c in _flatten_conditions(item)]
675685

676686

677687
def format_search_filter(term, params):

tests/sentry/issues/endpoints/test_group_event_details.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,23 @@ def test_query_title(self) -> None:
403403
assert response.data["previousEventID"] is None
404404
assert response.data["nextEventID"] is None
405405

406+
def test_query_title_not_in_with_wildcards(self) -> None:
407+
event_e = self.store_event(
408+
data={
409+
"event_id": "e" * 32,
410+
"environment": "staging",
411+
"timestamp": before_now(minutes=1).isoformat(),
412+
"fingerprint": ["group-title-wildcard"],
413+
"message": "some other title",
414+
},
415+
project_id=self.project_1.id,
416+
)
417+
418+
url = f"/api/0/issues/{event_e.group.id}/events/recommended/"
419+
response = self.client.get(url, {"query": '!title:["*value1*", "*value2*"]'}, format="json")
420+
421+
assert response.status_code == 200, response.content
422+
406423
def test_query_issue_platform_title(self) -> None:
407424
issue_title = "king of england"
408425
occurrence, group_info = self.process_occurrence(

0 commit comments

Comments
 (0)