Esempio n. 1
0
    def __init__(self, query, params, allow_minute_resolution=False):
        self.query = query.get("query", "")
        self.raw_fields = raw_fields = query.getlist("field", [])
        self.raw_groupby = raw_groupby = query.getlist("groupBy", [])

        if len(raw_fields) == 0:
            raise InvalidField('Request is missing a "field"')

        self.fields = {}
        for key in raw_fields:
            if key not in COLUMN_MAP:
                raise InvalidField(f'Invalid field: "{key}"')
            self.fields[key] = COLUMN_MAP[key]

        self.groupby = []
        for key in raw_groupby:
            if key not in GROUPBY_MAP:
                raise InvalidField(f'Invalid groupBy: "{key}"')
            self.groupby.append(GROUPBY_MAP[key])

        start, end, rollup = get_constrained_date_range(
            query, allow_minute_resolution)
        self.rollup = rollup
        self.start = start
        self.end = end

        self.params = params

        query_columns = set()
        for field in self.fields.values():
            query_columns.update(field.get_snuba_columns(raw_groupby))
        for groupby in self.groupby:
            query_columns.update(groupby.get_snuba_columns())
        self.query_columns = list(query_columns)

        query_groupby = set()
        for groupby in self.groupby:
            query_groupby.update(groupby.get_snuba_groupby())
        self.query_groupby = list(query_groupby)

        # the `params` are:
        # project_id, organization_id, environment;
        # also: start, end; but we got those ourselves.
        snuba_filter = get_filter(self.query, params)

        # this makes sure that literals in complex queries are properly quoted,
        # and unknown fields are raised as errors
        conditions = [
            resolve_condition(c, resolve_column)
            for c in snuba_filter.conditions
        ]

        self.aggregations = snuba_filter.aggregations
        self.conditions = conditions
        self.filter_keys = snuba_filter.filter_keys
Esempio n. 2
0
def resolve_discover_aliases(snuba_filter, function_translations=None):
    """
    Resolve the public schema aliases to the discover dataset.

    Returns a copy of the input structure, and includes a
    `translated_columns` key containing the selected fields that need to
    be renamed in the result set.
    """
    resolved = snuba_filter.clone()
    translated_columns = {}
    derived_columns = set()
    if function_translations:
        for snuba_name, sentry_name in six.iteritems(function_translations):
            derived_columns.add(snuba_name)
            translated_columns[snuba_name] = sentry_name

    selected_columns = resolved.selected_columns
    if selected_columns:
        for (idx, col) in enumerate(selected_columns):
            if isinstance(col, (list, tuple)):
                resolve_complex_column(col)
            else:
                name = resolve_column(col)
                selected_columns[idx] = name
                translated_columns[name] = col

        resolved.selected_columns = selected_columns

    groupby = resolved.groupby
    if groupby:
        for (idx, col) in enumerate(groupby):
            name = col
            if isinstance(col, (list, tuple)):
                if len(col) == 3:
                    name = col[2]
            elif col not in derived_columns:
                name = resolve_column(col)

            groupby[idx] = name
        resolved.groupby = groupby

    aggregations = resolved.aggregations
    for aggregation in aggregations or []:
        derived_columns.add(aggregation[2])
        if isinstance(aggregation[1], six.string_types):
            aggregation[1] = resolve_column(aggregation[1])
        elif isinstance(aggregation[1], (set, tuple, list)):
            aggregation[1] = [resolve_column(col) for col in aggregation[1]]
    resolved.aggregations = aggregations

    conditions = resolved.conditions
    if conditions:
        for (i, condition) in enumerate(conditions):
            replacement = resolve_condition(condition, resolve_column)
            conditions[i] = replacement
        resolved.conditions = [c for c in conditions if c]

    orderby = resolved.orderby
    if orderby:
        orderby = orderby if isinstance(orderby, (list, tuple)) else [orderby]
        resolved_orderby = []

        for field_with_order in orderby:
            field = field_with_order.lstrip("-")
            resolved_orderby.append(u"{}{}".format(
                "-" if field_with_order.startswith("-") else "",
                field if field in derived_columns else resolve_column(field),
            ))
        resolved.orderby = resolved_orderby
    return resolved, translated_columns
Esempio n. 3
0
def resolve_discover_aliases(snuba_args):
    """
    Resolve the public schema aliases to the discover dataset.

    Returns a copy of the input structure, and includes a
    `translated_columns` key containing the selected fields that need to
    be renamed in the result set.
    """
    resolved = deepcopy(snuba_args)
    translated_columns = {}
    derived_columns = set()

    selected_columns = resolved.get("selected_columns")
    if selected_columns:
        for (idx, col) in enumerate(selected_columns):
            if isinstance(col, (list, tuple)):
                raise ValueError(
                    "discover selected_columns should only be str. got %s" %
                    col)
            name = resolve_column(col)
            selected_columns[idx] = name
            translated_columns[name] = col
        resolved["selected_columns"] = selected_columns

    groupby = resolved.get("groupby")
    if groupby:
        for (idx, col) in enumerate(groupby):
            name = col
            if col not in derived_columns:
                name = resolve_column(col)
            groupby[idx] = name
        resolved["groupby"] = groupby

    aggregations = resolved.get("aggregations")
    for aggregation in aggregations or []:
        derived_columns.add(aggregation[2])
        if isinstance(aggregation[1], six.string_types):
            aggregation[1] = resolve_column(aggregation[1])
        elif isinstance(aggregation[1], (set, tuple, list)):
            aggregation[1] = [resolve_column(col) for col in aggregation[1]]
    resolved["aggregations"] = aggregations

    conditions = resolved.get("conditions")
    if conditions:
        for (i, condition) in enumerate(conditions):
            replacement = resolve_condition(condition, resolve_column)
            conditions[i] = replacement
        resolved["conditions"] = list(filter(None, conditions))

    # TODO add support for extracting having conditions.

    orderby = resolved.get("orderby")
    if orderby:
        orderby = orderby if isinstance(orderby, (list, tuple)) else [orderby]
        resolved_orderby = []

        for field_with_order in orderby:
            field = field_with_order.lstrip("-")
            resolved_orderby.append(u"{}{}".format(
                "-" if field_with_order.startswith("-") else "",
                field if field in derived_columns else resolve_column(field),
            ))
        resolved["orderby"] = resolved_orderby
    return resolved, translated_columns