fix: last-message JOIN uses rowid subquery, not timestamp equality (closes #282) - #283
Open
HalemoGPA wants to merge 1 commit into
Open
fix: last-message JOIN uses rowid subquery, not timestamp equality (closes #282)#283HalemoGPA wants to merge 1 commit into
HalemoGPA wants to merge 1 commit into
Conversation
list_chats, get_chat and get_direct_chat_by_contact all build the "last
message per chat" side of their result with
LEFT JOIN messages m ON c.jid = m.chat_jid
AND c.last_message_time = m.timestamp
which has two failure modes:
1. Drift: if c.last_message_time and messages.timestamp disagree by even
one microsecond (or one is a truncation of the other) the JOIN falls
through to NULL and the chat's last_message / last_sender /
last_is_from_me come back empty although messages exist.
2. Duplication: two messages in the same chat sharing an exact timestamp
(rapid consecutive sends, forwarded bursts) each match, so list_chats
returns one chat row per matching message.
Switching all three functions to a rowid subquery -
LEFT JOIN messages m ON m.rowid = (
SELECT rowid FROM messages
WHERE chat_jid = c.jid
ORDER BY timestamp DESC
LIMIT 1
)
- always joins to the actual latest message regardless of
last_message_time accuracy, and
- picks exactly one row on ties (deterministic LIMIT 1).
Closes lharries#282.
Reproduction fixture asserts:
- DriftChat (last_message_time one microsecond ahead of the actual
message.timestamp) now returns 'present-me!' instead of None.
- DupChat (two messages sharing '2026-06-25T10:00:00') returns exactly
one chat row.
- FineChat (aligned timestamps) still works.
- get_chat and get_direct_chat_by_contact all three FIXED behaviors.
Perf: with idx_messages_chat_time in place the subquery is a covering
index probe, so this change is neutral to slightly better on latency.
The motivation here is correctness; lharries#278 handles the perf story.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Per #282,
list_chats,get_chat, andget_direct_chat_by_contactall use:which has two failure modes shown below.
Reproduction
list_chatstoday:Fix
Switch all three functions to a rowid subquery:
last_message_timeaccuracy.LIMIT 1picks exactly one row).After the fix,
list_chatsreturns:Diff
whatsapp-mcp-server/whatsapp.py: 1 file, +26 / -7Verified
Fixture asserts all three fixed:
list_chats(limit=50)— DriftChat returns actual last message, DupChat single row.get_chat('c2@s.whatsapp.net').last_message=='present-me!'(wasNone).get_direct_chat_by_contact('c2').last_message=='present-me!'(wasNone).Perf note
Neutral to slightly better with
idx_messages_chat_time(from #278/PR #279 if merged) — the subquery becomes a covering index probe. The motivation here is correctness, not perf; #278 covers the perf story.What this closes
Closes #282.