diff --git a/snuba/query/mql/parser.py b/snuba/query/mql/parser.py index e3021f0f0c6..f0b4cbb95ab 100644 --- a/snuba/query/mql/parser.py +++ b/snuba/query/mql/parser.py @@ -7,6 +7,7 @@ import sentry_sdk from parsimonious.exceptions import IncompleteParseError from parsimonious.nodes import Node, NodeVisitor +from snuba_sdk import BooleanCondition, Condition from snuba_sdk.metrics_visitors import AGGREGATE_ALIAS from snuba_sdk.mql.mql import MQL_GRAMMAR @@ -342,12 +343,13 @@ def visit_filter_factor( # If we have a parenthesized expression, we just return it. return factor - condition_op, lhs, _, _, _, rhs = factor + condition_op, lhs, _, _, _, filter_factor_value = factor condition_op_value = ( "!" if len(condition_op) == 1 and condition_op[0] == "!" else "" ) - contains_wildcard, rhs = rhs + contains_wildcard = filter_factor_value.contains_wildcard + rhs = filter_factor_value.value if contains_wildcard: if not condition_op_value: @@ -450,36 +452,36 @@ def visit_tag_key(self, node: Node, children: Sequence[Any]) -> str: return node.text def visit_tag_value( - self, node: Node, children: Sequence[tuple[bool, Union[str, Sequence[str]]]] - ) -> tuple[bool, Union[str, Sequence[str]]]: - contains_wildcard, tag_value = children[0] - return contains_wildcard, tag_value + self, node: Node, children: Sequence[FilterFactorValue] + ) -> FilterFactorValue: + filter_factor_value = children[0] + return filter_factor_value def visit_quoted_suffix_wildcard_tag_value( self, node: Node, children: Sequence[Any] - ) -> tuple[bool, str]: + ) -> FilterFactorValue: _, text_before_wildcard, _, _ = children rhs = f"{text_before_wildcard}%" - return True, rhs + return FilterFactorValue(rhs, True) def visit_suffix_wildcard_tag_value( self, node: Node, children: Sequence[Any] - ) -> tuple[bool, str]: + ) -> FilterFactorValue: text_before_wildcard, _ = children rhs = f"{text_before_wildcard}%" - return True, rhs + return FilterFactorValue(rhs, True) def visit_quoted_string_filter( self, node: Node, children: Sequence[Any] - ) -> tuple[bool, str]: + ) -> FilterFactorValue: text = str(node.text[1:-1]) match = text.replace('\\"', '"') - return False, match + return FilterFactorValue(match, False) def visit_unquoted_string_filter( self, node: Node, children: Sequence[Any] - ) -> tuple[bool, str]: - return False, str(node.text) + ) -> FilterFactorValue: + return FilterFactorValue(str(node.text), False) def visit_unquoted_string(self, node: Node, children: Sequence[Any]) -> str: assert isinstance(node.text, str) @@ -492,9 +494,11 @@ def visit_quoted_string(self, node: Node, children: Sequence[Any]) -> str: def visit_string_tuple( self, node: Node, children: Sequence[Any] - ) -> tuple[bool, Sequence[str]]: + ) -> FilterFactorValue: _, _, first, zero_or_more_others, _, _ = children - return False, [first[0], *(v[0] for _, _, _, v in zero_or_more_others)] + return FilterFactorValue( + [first[0], *(v[0] for _, _, _, v in zero_or_more_others)], False + ) def visit_group_by_name(self, node: Node, children: Sequence[Any]) -> str: assert isinstance(node.text, str) @@ -1257,3 +1261,9 @@ def _process_data( _post_process(query, VALIDATORS) return query + + +@dataclass +class FilterFactorValue(object): + value: str | Sequence[str] | Condition | BooleanCondition + contains_wildcard: bool