Browse Source

fix(query-builder): Search non-nullable key for empty value (#50205)

When searching for empty values, non-nullable keys should not use
`isNull`.
Tony Xiao 1 year ago
parent
commit
0606388075

+ 1 - 1
src/sentry/search/events/builder/discover.py

@@ -1331,7 +1331,7 @@ class QueryBuilder(BaseQueryBuilder):
 
         # Handle checks for existence
         if search_filter.operator in ("=", "!=") and search_filter.value.value == "":
-            if is_tag or is_context:
+            if is_tag or is_context or name in self.config.non_nullable_keys:
                 return Condition(lhs, Op(search_filter.operator), value)
             else:
                 # If not a tag, we can just check that the column is null.

+ 3 - 10
src/sentry/search/events/datasets/profile_functions.py

@@ -74,7 +74,6 @@ COLUMNS = [
     Column(alias="platform.name", column="platform", kind=Kind.STRING),
     Column(alias="environment", column="environment", kind=Kind.STRING),
     Column(alias="release", column="release", kind=Kind.STRING),
-    Column(alias="retention_days", column="retention_days", kind=Kind.INTEGER),
     Column(
         alias="function.duration",
         column="percentiles",
@@ -126,19 +125,13 @@ class ProfileFunctionsDatasetConfig(DatasetConfig):
     non_nullable_keys = {
         "project.id",
         "project_id",
-        "transaction_name",
+        "transaction",
         "timestamp",
-        "depth",
-        "parent_fingerprint",
         "fingerprint",
-        "name",
+        "function",
         "package",
-        "path",
         "is_application",
-        "platform",
-        "os_name",
-        "os_version",
-        "retention_days",
+        "platform.name",
     }
 
     def __init__(self, builder: builder.QueryBuilder):

+ 71 - 0
tests/sentry/search/events/builder/test_profile_functions.py

@@ -0,0 +1,71 @@
+from datetime import datetime, timedelta
+
+import pytest
+from django.utils import timezone
+from snuba_sdk.column import Column
+from snuba_sdk.conditions import Condition, Op
+
+from sentry.search.events.builder.profile_functions import ProfileFunctionsQueryBuilder
+from sentry.testutils.factories import Factories
+from sentry.utils.snuba import Dataset
+
+# pin a timestamp for now so tests results dont change
+now = datetime(2022, 10, 31, 0, 0, tzinfo=timezone.utc)
+today = now.replace(hour=0, minute=0, second=0, microsecond=0)
+
+
+@pytest.fixture
+def params():
+    organization = Factories.create_organization()
+    team = Factories.create_team(organization=organization)
+    project1 = Factories.create_project(organization=organization, teams=[team])
+    project2 = Factories.create_project(organization=organization, teams=[team])
+
+    user = Factories.create_user()
+    Factories.create_team_membership(team=team, user=user)
+
+    return {
+        "start": now - timedelta(days=7),
+        "end": now - timedelta(seconds=1),
+        "project_id": [project1.id, project2.id],
+        "project_objects": [project1, project2],
+        "organization_id": organization.id,
+        "user_id": user.id,
+        "team_id": [team.id],
+    }
+
+
+@pytest.mark.parametrize(
+    "search,condition",
+    [
+        pytest.param(
+            'package:""',
+            Condition(Column("package"), Op("="), ""),
+            id="empty package",
+        ),
+        pytest.param(
+            '!package:""',
+            Condition(Column("package"), Op("!="), ""),
+            id="not empty package",
+        ),
+        pytest.param(
+            'function:""',
+            Condition(Column("name"), Op("="), ""),
+            id="empty function",
+        ),
+        pytest.param(
+            '!function:""',
+            Condition(Column("name"), Op("!="), ""),
+            id="not empty function",
+        ),
+    ],
+)
+@pytest.mark.django_db
+def test_conditions(params, search, condition):
+    builder = ProfileFunctionsQueryBuilder(
+        Dataset.Functions,
+        params,
+        query=search,
+        selected_columns=["count()"],
+    )
+    assert condition in builder.where

+ 0 - 7
tests/snuba/api/endpoints/test_organization_events.py

@@ -5878,7 +5878,6 @@ class OrganizationEventsProfileFunctionsDatasetEndpointTest(OrganizationEventsEn
                         "project": "python",
                         "release": "backend@1",
                         "platform.name": "python",
-                        "retention_days": 90,
                         "package": "lib_foo",
                         "environment": "development",
                         "p50()": 34695708.0,
@@ -5923,10 +5922,6 @@ class OrganizationEventsProfileFunctionsDatasetEndpointTest(OrganizationEventsEn
                         "name": "platform.name",
                         "type": "String",
                     },
-                    {
-                        "name": "retention_days",
-                        "type": "UInt16",
-                    },
                     {
                         "name": "package",
                         "type": "String",
@@ -5980,7 +5975,6 @@ class OrganizationEventsProfileFunctionsDatasetEndpointTest(OrganizationEventsEn
             "platform.name",
             "environment",
             "release",
-            "retention_days",
             "count()",
             "examples()",
             "p50()",
@@ -6015,7 +6009,6 @@ class OrganizationEventsProfileFunctionsDatasetEndpointTest(OrganizationEventsEn
             "platform.name": None,
             "environment": None,
             "release": None,
-            "retention_days": None,
             "count()": None,
             "examples()": None,
             "p50()": "nanosecond",