diff --git a/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py b/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py index 104e232a01406..09a7389e74c7b 100644 --- a/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py +++ b/posthog/hogql_queries/insights/trends/test/test_trends_query_runner.py @@ -364,6 +364,19 @@ def test_trends_query_formula(self): self.assertEqual("Formula (A+B)", response.results[0]["label"]) self.assertEqual([1, 0, 2, 4, 4, 0, 2, 1, 1, 0, 1], response.results[0]["data"]) + def test_trends_query_formula_breakdown_no_data(self): + self._create_test_events() + + response = self._run_trends_query( + self.default_date_from, + self.default_date_to, + IntervalType.day, + [EventsNode(event="$pageviewxxx"), EventsNode(event="$pageleavexxx")], + TrendsFilter(formula="A+B"), + BreakdownFilter(breakdown_type=BreakdownType.person, breakdown="$browser"), + ) + self.assertEqual([], response.results) + def test_trends_query_formula_aggregate(self): self._create_test_events() @@ -1114,6 +1127,38 @@ def test_breakdown_values_limit(self): ) self.assertEqual(len(response.results), 11) + def test_breakdown_values_unknown_property(self): + # same as above test, just without creating the property definition + for value in list(range(30)): + _create_event( + team=self.team, + event="$pageview", + distinct_id=f"person_{value}", + timestamp="2020-01-11T12:00:00Z", + properties={"breakdown_value": f"{value}"}, + ) + + response = self._run_trends_query( + "2020-01-09", + "2020-01-20", + IntervalType.day, + [EventsNode(event="$pageview")], + TrendsFilter(display=ChartDisplayType.ActionsLineGraph), + BreakdownFilter(breakdown="breakdown_value", breakdown_type=BreakdownType.event), + ) + + self.assertEqual(len(response.results), 26) + + response = self._run_trends_query( + "2020-01-09", + "2020-01-20", + IntervalType.day, + [EventsNode(event="$pageview")], + TrendsFilter(display=ChartDisplayType.ActionsLineGraph), + BreakdownFilter(breakdown="breakdown_value", breakdown_type=BreakdownType.event, breakdown_limit=10), + ) + self.assertEqual(len(response.results), 11) + def test_breakdown_values_world_map_limit(self): PropertyDefinition.objects.create(team=self.team, name="breakdown_value", property_type="String") diff --git a/posthog/hogql_queries/insights/trends/trends_query_runner.py b/posthog/hogql_queries/insights/trends/trends_query_runner.py index 40f26664c2585..b698e095e8b09 100644 --- a/posthog/hogql_queries/insights/trends/trends_query_runner.py +++ b/posthog/hogql_queries/insights/trends/trends_query_runner.py @@ -666,25 +666,27 @@ def apply_formula(self, formula: str, results: List[Dict[str, Any]]) -> List[Dic res.append(new_result) return res - if self._trends_display.should_aggregate_values(): - series_data = list(map(lambda s: [s["aggregated_value"]], results)) - new_series_data = FormulaAST(series_data).call(formula) - - new_result = results[0] - new_result["aggregated_value"] = float(sum(new_series_data)) - new_result["data"] = None - new_result["count"] = 0 - new_result["label"] = f"Formula ({formula})" - else: - series_data = list(map(lambda s: s["data"], results)) - new_series_data = FormulaAST(series_data).call(formula) + if len(results) > 0: + if self._trends_display.should_aggregate_values(): + series_data = list(map(lambda s: [s["aggregated_value"]], results)) + new_series_data = FormulaAST(series_data).call(formula) + + new_result = results[0] + new_result["aggregated_value"] = float(sum(new_series_data)) + new_result["data"] = None + new_result["count"] = 0 + new_result["label"] = f"Formula ({formula})" + else: + series_data = list(map(lambda s: s["data"], results)) + new_series_data = FormulaAST(series_data).call(formula) - new_result = results[0] - new_result["data"] = new_series_data - new_result["count"] = float(sum(new_series_data)) - new_result["label"] = f"Formula ({formula})" + new_result = results[0] + new_result["data"] = new_series_data + new_result["count"] = float(sum(new_series_data)) + new_result["label"] = f"Formula ({formula})" - return [new_result] + return [new_result] + return [] def _is_breakdown_field_boolean(self): if not self.query.breakdownFilter or not self.query.breakdownFilter.breakdown_type: @@ -741,13 +743,19 @@ def _event_property( field: str, field_type: PropertyDefinition.Type, group_type_index: Optional[int], - ): - return PropertyDefinition.objects.get( - name=field, - team=self.team, - type=field_type, - group_type_index=group_type_index if field_type == PropertyDefinition.Type.GROUP else None, - ).property_type + ) -> str: + try: + return ( + PropertyDefinition.objects.get( + name=field, + team=self.team, + type=field_type, + group_type_index=group_type_index if field_type == PropertyDefinition.Type.GROUP else None, + ).property_type + or "String" + ) + except PropertyDefinition.DoesNotExist: + return "String" # TODO: Move this to posthog/hogql_queries/legacy_compatibility/query_to_filter.py def _query_to_filter(self) -> Dict[str, Any]: