From c0c38f2c749cab90d469df1c546cb0a5c16d1471 Mon Sep 17 00:00:00 2001 From: Nar Saynorath Date: Fri, 30 May 2025 09:58:24 -0400 Subject: [PATCH 1/2] fix(ownership-rules): Update email filter to create less conditions Trying to improve the performance of this filter. The current implementation creates an OR condition and calls upper on both the column and the email of the condition for each email passed. This reduces it to a single IN check and a single usage of `upper` to do the case insensitive check. --- src/sentry/users/services/user/impl.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sentry/users/services/user/impl.py b/src/sentry/users/services/user/impl.py index 020c3ec6cc3ea7..1a75ae368ae64c 100644 --- a/src/sentry/users/services/user/impl.py +++ b/src/sentry/users/services/user/impl.py @@ -7,6 +7,7 @@ from django.db import router, transaction from django.db.models import F, Q, QuerySet +from django.db.models.functions import Upper from django.utils.text import slugify from sentry.api.serializers.base import Serializer, serialize @@ -313,7 +314,12 @@ def apply_filters(self, query: QuerySet[User], filters: UserFilterArgs) -> Query if "email_verified" in filters: query = query.filter(emails__is_verified=filters["email_verified"]) if "emails" in filters: - query = query.filter(in_iexact("emails__email", filters["emails"])) + # Since we can have a lot of emails, the in_iexact helper creates too many + # conditions in the query, so we annotate the email and filter by the + # lowercased version of the email for case insensitive search + query = query.annotate(lower_emails__email=Upper("emails__email")).filter( + lower_emails__email__in=map(lambda x: x.upper(), filters["emails"]) + ) if "query" in filters: query = query.filter( Q(emails__email__icontains=filters["query"]) From c6b78fb8bfe465f20ac415889f84afdd0ce22e71 Mon Sep 17 00:00:00 2001 From: Nar Saynorath Date: Fri, 30 May 2025 11:32:58 -0400 Subject: [PATCH 2/2] Fix annotation --- src/sentry/users/services/user/impl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sentry/users/services/user/impl.py b/src/sentry/users/services/user/impl.py index 1a75ae368ae64c..3ffb87acdb256e 100644 --- a/src/sentry/users/services/user/impl.py +++ b/src/sentry/users/services/user/impl.py @@ -316,9 +316,9 @@ def apply_filters(self, query: QuerySet[User], filters: UserFilterArgs) -> Query if "emails" in filters: # Since we can have a lot of emails, the in_iexact helper creates too many # conditions in the query, so we annotate the email and filter by the - # lowercased version of the email for case insensitive search - query = query.annotate(lower_emails__email=Upper("emails__email")).filter( - lower_emails__email__in=map(lambda x: x.upper(), filters["emails"]) + # uppercased version of the email for case insensitive search + query = query.annotate(upper_emails=Upper("emails__email")).filter( + upper_emails__in=map(lambda x: x.upper(), filters["emails"]) ) if "query" in filters: query = query.filter(