Esempio n. 1
0
def resolve_condition(cond):
    """
    When conditions have been parsed by the api.event_search module
    we can end up with conditions that are not valid on the current dataset
    due to how ap.event_search checks for valid field names without
    being aware of the dataset.

    We have the dataset context here, so we need to re-scope conditions to the
    current dataset.
    """
    index = get_function_index(cond)
    if index is not None:
        # IN conditions are detected as a function but aren't really.
        if cond[index] == "IN":
            cond[0] = resolve_column(cond[0])
            return cond

        func_args = cond[index + 1]
        for (i, arg) in enumerate(func_args):
            # Nested function
            if isinstance(arg, (list, tuple)):
                func_args[i] = resolve_condition(arg)
            else:
                func_args[i] = resolve_column(arg)
        cond[index + 1] = func_args
        return cond

    # No function name found
    if isinstance(cond, (list, tuple)) and len(cond):
        # Condition is [col, operator, value]
        if isinstance(cond[0], six.string_types) and len(cond) == 3:
            cond[0] = resolve_column(cond[0])
            return cond
        if isinstance(cond[0], (list, tuple)):
            if get_function_index(cond[0]) is not None:
                cond[0] = resolve_condition(cond[0])
                return cond
            else:
                # Nested conditions
                return [resolve_condition(item) for item in cond]
    raise ValueError("Unexpected condition format %s" % cond)
Esempio n. 2
0
def parse_columns_in_functions(col, context=None, index=None):
    """
    Checks expressions for arguments that should be considered a column while
    ignoring strings that represent clickhouse function names

    if col is a list, means the expression has functions and we need
    to parse for arguments that should be considered column names.

    Assumptions here:
     * strings that represent clickhouse function names are always followed by a list or tuple
     * strings that are quoted with single quotes are used as string literals for CH
     * otherwise we should attempt to get the snuba column name (or custom tag)
    """

    function_name_index = get_function_index(col)

    if function_name_index is not None:
        # if this is non zero, that means there are strings before this index
        # that should be converted to snuba column names
        # e.g. ['func1', ['column', 'func2', ['arg1']]]
        if function_name_index > 0:
            for i in range(0, function_name_index):
                if context is not None:
                    context[i] = get_snuba_column_name(col[i])

        args = col[function_name_index + 1]

        # check for nested functions in args
        if get_function_index(args):
            # look for columns
            return parse_columns_in_functions(args, args)

        # check each argument for column names
        else:
            for (i, arg) in enumerate(args):
                parse_columns_in_functions(arg, args, i)
    else:
        # probably a column name
        if context is not None and index is not None:
            context[index] = get_snuba_column_name(col)