def visit_or_expression( self, node: Node, visited_children: Tuple[Any, Expression, Any, Expression]) -> Expression: _, left_condition, _, or_condition = visited_children args = [left_condition] # in the case of one Condition # or_condition will be an empty Node if isinstance(or_condition, Node): return left_condition if isinstance(or_condition, (AndTuple, OrTuple)): _, exp = or_condition return combine_or_conditions([left_condition, exp]) elif isinstance(or_condition, list): for elem in or_condition: _, exp = elem args.append(exp) return combine_or_conditions(args)
def generate_bloom_filter_condition( column_name: str, single_filtered: Dict[str, Sequence[str]], multiple_filtered: Dict[Tuple[str, ...], Sequence[Tuple[str, ...]]], ) -> Optional[Expression]: """ Generate the filters on the array columns to use the bloom filter index on the spans.op and spans.group columns in order to filter the transactions prior to the array join. The bloom filter index is requires the use of the has function, therefore the final condition is built up from a series of has conditions. """ per_key_vals: Dict[str, Set[str]] = defaultdict(set) for key, single_filter in single_filtered.items(): for val in single_filter: per_key_vals[key].add(val) for keys, multiple_filter in multiple_filtered.items(): for val_tuple in multiple_filter: for key, val in zip(keys, val_tuple): per_key_vals[key].add(val) conditions = [ combine_or_conditions([ FunctionCallExpr( None, "has", (ColumnExpr(None, None, key), LiteralExpr(None, val)), ) for val in sorted(vals) ]) for key, vals in per_key_vals.items() ] return combine_and_conditions(conditions) if conditions else None
def or_builder(expressions: Sequence[Expression]) -> Optional[Expression]: if not expressions: return None return combine_or_conditions(expressions)
def _get_condition_without_redundant_checks( self, condition: Expression, query: Query ) -> Expression: """Optimizes the case where the query condition contains the following: valueOf('my_tag') != '' AND valueOf('my_tag') == "something" ^ ^ | | existence check value check the existence check in this clause is redundant and prevents the hashmap optimization from being applied. This function will remove all tag existence checks from the condition IFF they are ANDed with a value check for the *same tag name* Side effects: This function works by flattening first level AND conditions to find clauses where existence checks and value checks are ANDed together. When the AND conditions are recombined, they are not guaranteed to be in the same structure (but are guaranteed to be functionally equivalent) Example: ┌───┐ ┌───┐ │AND│ │AND│ ├──┬┘ └┬──┤ │ │ │ │ ┌──┴┐ c a ┌┴──┐ │AND│ becomes │AND│ └┬─┬┘ ├──┬┘ │ │ │ │ a b b c """ if not isinstance(condition, FunctionExpr): return condition elif condition.function_name == BooleanFunctions.OR: sub_conditions = get_first_level_or_conditions(condition) pruned_conditions = [ self._get_condition_without_redundant_checks(c, query) for c in sub_conditions ] return combine_or_conditions(pruned_conditions) elif condition.function_name == BooleanFunctions.AND: sub_conditions = get_first_level_and_conditions(condition) tag_eq_match_strings = set() matched_tag_exists_conditions = {} for condition_id, cond in enumerate(sub_conditions): tag_exist_match = None for tag_exists_pattern in self.__tag_exists_patterns: tag_exist_match = tag_exists_pattern.match(cond) if tag_exist_match: matched_tag_exists_conditions[condition_id] = tag_exist_match if not tag_exist_match: eq_match = self.__optimizable_pattern.match(cond) if eq_match: tag_eq_match_strings.add(eq_match.string(KEY_MAPPING_PARAM)) useful_conditions = [] for condition_id, cond in enumerate(sub_conditions): tag_exist_match = matched_tag_exists_conditions.get(condition_id, None) if tag_exist_match: requested_tag = tag_exist_match.string("key") if requested_tag in tag_eq_match_strings: # the clause is redundant, thus we continue the loop # and do not add it to useful_conditions continue useful_conditions.append( self._get_condition_without_redundant_checks(cond, query) ) return combine_and_conditions(useful_conditions) else: return condition