models: Always search Messages with a realm_id or id limit.

Unless there is a limit on `id`, always provide a `realm_id` limit as
well.  We also notate which index is expected to be used in each
query.
This commit is contained in:
Alex Vandiver
2023-08-30 19:19:37 +00:00
committed by Tim Abbott
parent f9dd2549eb
commit b94402152d
34 changed files with 249 additions and 65 deletions

View File

@@ -92,8 +92,12 @@ def filter_by_topic_name_via_message(
return query.filter(message__subject__iexact=topic_name)
def messages_for_topic(stream_recipient_id: int, topic_name: str) -> QuerySet[Message]:
def messages_for_topic(
realm_id: int, stream_recipient_id: int, topic_name: str
) -> QuerySet[Message]:
return Message.objects.filter(
# Uses index: zerver_message_realm_recipient_upper_subject
realm_id=realm_id,
recipient_id=stream_recipient_id,
subject__iexact=topic_name,
)
@@ -149,13 +153,17 @@ def update_messages_for_topic_edit(
edit_history_event: EditHistoryEvent,
last_edit_time: datetime,
) -> List[Message]:
propagate_query = Q(recipient_id=old_stream.recipient_id, subject__iexact=orig_topic_name)
propagate_query = Q(
recipient_id=old_stream.recipient_id,
subject__iexact=orig_topic_name,
)
if propagate_mode == "change_all":
propagate_query = propagate_query & ~Q(id=edited_message.id)
if propagate_mode == "change_later":
propagate_query = propagate_query & Q(id__gt=edited_message.id)
messages = Message.objects.filter(propagate_query).select_related(
# Uses index: zerver_message_realm_recipient_upper_subject
messages = Message.objects.filter(propagate_query, realm_id=old_stream.realm_id).select_related(
*Message.DEFAULT_SELECT_RELATED
)
@@ -283,12 +291,17 @@ def get_topic_resolution_and_bare_name(stored_name: str) -> Tuple[bool, str]:
return (False, stored_name)
def participants_for_topic(recipient_id: int, topic_name: str) -> Set[int]:
def participants_for_topic(realm_id: int, recipient_id: int, topic_name: str) -> Set[int]:
"""
Users who either sent or reacted to the messages in the topic.
The function is expensive for large numbers of messages in the topic.
"""
messages = Message.objects.filter(recipient_id=recipient_id, subject__iexact=topic_name)
messages = Message.objects.filter(
# Uses index: zerver_message_realm_recipient_upper_subject
realm_id=realm_id,
recipient_id=recipient_id,
subject__iexact=topic_name,
)
participants = set(
UserProfile.objects.filter(
Q(id__in=Subquery(messages.values("sender_id")))