|
@@ -38,9 +38,11 @@ from sentry.search.eap import constants
|
|
|
from sentry.search.eap.columns import (
|
|
|
AggregateDefinition,
|
|
|
ColumnDefinitions,
|
|
|
+ ConditionalAggregateDefinition,
|
|
|
FormulaDefinition,
|
|
|
ResolvedAggregate,
|
|
|
ResolvedAttribute,
|
|
|
+ ResolvedConditionalAggregate,
|
|
|
ResolvedFormula,
|
|
|
VirtualColumnDefinition,
|
|
|
)
|
|
@@ -65,7 +67,11 @@ class SearchResolver:
|
|
|
str, tuple[ResolvedAttribute, VirtualColumnDefinition | None]
|
|
|
] = field(default_factory=dict)
|
|
|
_resolved_function_cache: dict[
|
|
|
- str, tuple[ResolvedFormula | ResolvedAggregate, VirtualColumnDefinition | None]
|
|
|
+ str,
|
|
|
+ tuple[
|
|
|
+ ResolvedFormula | ResolvedAggregate | ResolvedConditionalAggregate,
|
|
|
+ VirtualColumnDefinition | None,
|
|
|
+ ],
|
|
|
] = field(default_factory=dict)
|
|
|
|
|
|
@sentry_sdk.trace
|
|
@@ -553,7 +559,9 @@ class SearchResolver:
|
|
|
|
|
|
@sentry_sdk.trace
|
|
|
def resolve_columns(self, selected_columns: list[str]) -> tuple[
|
|
|
- list[ResolvedAttribute | ResolvedAggregate | ResolvedFormula],
|
|
|
+ list[
|
|
|
+ ResolvedAttribute | ResolvedAggregate | ResolvedConditionalAggregate | ResolvedFormula
|
|
|
+ ],
|
|
|
list[VirtualColumnDefinition | None],
|
|
|
]:
|
|
|
"""Given a list of columns resolve them and get their context if applicable
|
|
@@ -588,10 +596,9 @@ class SearchResolver:
|
|
|
|
|
|
return resolved_columns, resolved_contexts
|
|
|
|
|
|
- def resolve_column(
|
|
|
- self, column: str, match: Match | None = None
|
|
|
- ) -> tuple[
|
|
|
- ResolvedAttribute | ResolvedAggregate | ResolvedFormula, VirtualColumnDefinition | None
|
|
|
+ def resolve_column(self, column: str, match: Match | None = None) -> tuple[
|
|
|
+ ResolvedAttribute | ResolvedAggregate | ResolvedConditionalAggregate | ResolvedFormula,
|
|
|
+ VirtualColumnDefinition | None,
|
|
|
]:
|
|
|
"""Column is either an attribute or an aggregate, this function will determine which it is and call the relevant
|
|
|
resolve function"""
|
|
@@ -672,9 +679,10 @@ class SearchResolver:
|
|
|
raise InvalidSearchQuery(f"Could not parse {column}")
|
|
|
|
|
|
@sentry_sdk.trace
|
|
|
- def resolve_functions(
|
|
|
- self, columns: list[str]
|
|
|
- ) -> tuple[list[ResolvedFormula | ResolvedAggregate], list[VirtualColumnDefinition | None]]:
|
|
|
+ def resolve_functions(self, columns: list[str]) -> tuple[
|
|
|
+ list[ResolvedFormula | ResolvedAggregate | ResolvedConditionalAggregate],
|
|
|
+ list[VirtualColumnDefinition | None],
|
|
|
+ ]:
|
|
|
"""Helper function to resolve a list of functions instead of 1 attribute at a time"""
|
|
|
resolved_functions, resolved_contexts = [], []
|
|
|
for column in columns:
|
|
@@ -683,9 +691,10 @@ class SearchResolver:
|
|
|
resolved_contexts.append(context)
|
|
|
return resolved_functions, resolved_contexts
|
|
|
|
|
|
- def resolve_function(
|
|
|
- self, column: str, match: Match | None = None
|
|
|
- ) -> tuple[ResolvedFormula | ResolvedAggregate, VirtualColumnDefinition | None]:
|
|
|
+ def resolve_function(self, column: str, match: Match | None = None) -> tuple[
|
|
|
+ ResolvedFormula | ResolvedAggregate | ResolvedConditionalAggregate,
|
|
|
+ VirtualColumnDefinition | None,
|
|
|
+ ]:
|
|
|
if column in self._resolved_function_cache:
|
|
|
return self._resolved_function_cache[column]
|
|
|
# Check if the column looks like a function (matches a pattern), parse the function name and args out
|
|
@@ -700,11 +709,15 @@ class SearchResolver:
|
|
|
alias = match.group("alias") or column
|
|
|
|
|
|
# Get the function definition
|
|
|
- function_definition: AggregateDefinition | FormulaDefinition
|
|
|
+ function_definition: (
|
|
|
+ AggregateDefinition | FormulaDefinition | ConditionalAggregateDefinition
|
|
|
+ )
|
|
|
if function in self.definitions.aggregates:
|
|
|
function_definition = self.definitions.aggregates[function]
|
|
|
elif function in self.definitions.formulas:
|
|
|
function_definition = self.definitions.formulas[function]
|
|
|
+ elif function in self.definitions.conditional_aggregates:
|
|
|
+ function_definition = self.definitions.conditional_aggregates[function]
|
|
|
else:
|
|
|
raise InvalidSearchQuery(f"Unknown function {function}")
|
|
|
|