예제 #1
0
    def visit_aggregate_duration_filter(self, node, children):
        (negation, search_key, _, operator, search_value) = children
        operator = handle_negation(negation, operator)

        try:
            # Even if the search value matches duration format, only act as
            # duration for certain columns
            function = resolve_field(search_key.name, self.params, functions_acl=FUNCTIONS.keys())

            is_duration_key = False
            if function.aggregate is not None:
                args = function.aggregate[1]
                if isinstance(args, list):
                    is_duration_key = all(self.is_duration_key(arg) for arg in args)
                else:
                    is_duration_key = self.is_duration_key(args)

            if is_duration_key:
                aggregate_value = parse_duration(*search_value)
            else:
                # Duration overlaps with numeric values with `m` (million vs
                # minutes). So we fall through to numeric if it's not a
                # duration key
                #
                # TODO(epurkhiser): Should we validate that the field is
                # numeric and do some other fallback if it's not?
                aggregate_value = parse_numeric_value(*search_value)
        except ValueError:
            raise InvalidSearchQuery(f"Invalid aggregate query condition: {search_key}")
        except InvalidQuery as exc:
            raise InvalidSearchQuery(str(exc))

        return AggregateFilter(search_key, operator, SearchValue(aggregate_value))
예제 #2
0
    def visit_aggregate_filter(self, node, children):
        (negation, search_key, _, operator, search_value) = children
        operator = self.handle_negation(negation, operator)
        search_value = search_value[0] if not isinstance(search_value, RegexNode) else search_value

        try:
            aggregate_value = None
            if search_value.expr_name in ["duration_format", "percentage_format"]:
                # Even if the search value matches duration format, only act as duration for certain columns
                function = resolve_field(
                    search_key.name, self.params, functions_acl=FUNCTIONS.keys()
                )
                if function.aggregate is not None:
                    if search_value.expr_name == "percentage_format" and self.is_percentage_key(
                        function.aggregate[0]
                    ):
                        aggregate_value = parse_percentage(*search_value.match.groups())
                    # Extract column and function name out so we can check if we should parse as duration
                    elif search_value.expr_name == "duration_format" and self.is_duration_key(
                        function.aggregate[1]
                    ):
                        aggregate_value = parse_duration(*search_value.match.groups())

            if aggregate_value is None:
                aggregate_value = parse_numeric_value(*search_value.match.groups())
        except ValueError:
            raise InvalidSearchQuery(f"Invalid aggregate query condition: {search_key}")
        except InvalidQuery as exc:
            raise InvalidSearchQuery(str(exc))
        return AggregateFilter(search_key, operator, SearchValue(aggregate_value))
예제 #3
0
    def visit_aggregate_percentage_filter(self, node, children):
        (negation, search_key, _, operator, search_value) = children
        operator = handle_negation(negation, operator)

        aggregate_value = None

        try:
            # Even if the search value matches percentage format, only act as
            # percentage for certain columns
            function = resolve_field(search_key.name,
                                     self.params,
                                     functions_acl=FUNCTIONS.keys())
            if function.aggregate is not None and self.is_percentage_key(
                    function.aggregate[0]):
                aggregate_value = parse_percentage(search_value)
        except ValueError:
            raise InvalidSearchQuery(
                f"Invalid aggregate query condition: {search_key}")
        except InvalidQuery as exc:
            raise InvalidSearchQuery(str(exc))

        if aggregate_value is not None:
            return AggregateFilter(search_key, operator,
                                   SearchValue(aggregate_value))

        # Invalid formats fall back to text match
        search_value = operator + search_value if operator != "=" else search_value
        return AggregateFilter(search_key, "=", SearchValue(search_value))
예제 #4
0
def convert_aggregate_filter_to_snuba_query(aggregate_filter, params):
    name = aggregate_filter.key.name
    value = aggregate_filter.value.value

    if params is not None and name in params.get("aliases", {}):
        return params["aliases"][name].converter(aggregate_filter)

    value = (int(to_timestamp(value))
             if isinstance(value, datetime) and name != "timestamp" else value)

    if aggregate_filter.operator in (
            "=", "!=") and aggregate_filter.value.value == "":
        return [["isNull", [name]], aggregate_filter.operator, 1]

    function = resolve_field(name, params, functions_acl=FUNCTIONS.keys())
    if function.aggregate is not None:
        name = function.aggregate[-1]

    return [name, aggregate_filter.operator, value]