core: delete members with messages (#5711)

* core: delete members with messages (WIP)

* remove messages

* fix, test

* update query plans
This commit is contained in:
Evgeny authored and GitHub committed 2025-03-07 07:47:32 +00:00
1 parent 5bef7349d8
commit a6631ce629
11 files changed
+302 -92

No files matched your search

+73 -12
View File
@@ -21,6 +21,7 @@ module Simplex.Chat.Store.Messages
-- * Message and chat item functions
deleteContactCIs,
getGroupFileInfo,
getGroupMemberFileInfo,
deleteGroupChatItemsMessages,
createNewSndMessage,
createSndMsgDelivery,
@@ -57,8 +58,10 @@ module Simplex.Chat.Store.Messages
updateGroupCIMentions,
deleteGroupChatItem,
updateGroupChatItemModerated,
updateMemberCIsModerated,
updateGroupCIBlockedByAdmin,
markGroupChatItemDeleted,
markMemberCIsDeleted,
markGroupChatItemBlocked,
markGroupCIBlockedByAdmin,
markMessageReportsDeleted,
@@ -193,6 +196,11 @@ getGroupFileInfo db User {userId} GroupInfo {groupId} =
map toFileInfo
<$> DB.query db (fileInfoQuery <> " WHERE i.user_id = ? AND i.group_id = ?") (userId, groupId)
getGroupMemberFileInfo :: DB.Connection -> User -> GroupInfo -> GroupMember -> IO [CIFileInfo]
getGroupMemberFileInfo db User {userId} GroupInfo {groupId} GroupMember {groupMemberId} =
map toFileInfo
<$> DB.query db (fileInfoQuery <> " WHERE i.user_id = ? AND i.group_id = ? AND i.group_member_id = ?") (userId, groupId, groupMemberId)
deleteGroupChatItemsMessages :: DB.Connection -> User -> GroupInfo -> IO ()
deleteGroupChatItemsMessages db User {userId} GroupInfo {groupId} = do
DB.execute db "DELETE FROM messages WHERE group_id = ?" (Only groupId)
@@ -2150,18 +2158,18 @@ deleteDirectChatItem db User {userId} Contact {contactId} ci = do
(userId, contactId, itemId)
deleteChatItemMessages_ :: DB.Connection -> ChatItemId -> IO ()
deleteChatItemMessages_ db itemId =
DB.execute
db
[sql|
DELETE FROM messages
WHERE message_id IN (
SELECT message_id
FROM chat_item_messages
WHERE chat_item_id = ?
)
|]
(Only itemId)
deleteChatItemMessages_ db itemId = DB.execute db deleteChatItemMessagesQuery (Only itemId)
deleteChatItemMessagesQuery :: Query
deleteChatItemMessagesQuery =
[sql|
DELETE FROM messages
WHERE message_id IN (
SELECT message_id
FROM chat_item_messages
WHERE chat_item_id = ?
)
|]
deleteChatItemVersions_ :: DB.Connection -> ChatItemId -> IO ()
deleteChatItemVersions_ db itemId =
@@ -2359,6 +2367,34 @@ updateGroupChatItemModerated db User {userId} GroupInfo {groupId} ci m@GroupMemb
(deletedTs, groupMemberId, toContent, toText, currentTs, userId, groupId, itemId)
pure ci {content = toContent, meta = (meta ci) {itemText = toText, itemDeleted = Just (CIModerated (Just deletedTs) m), editable = False, deletable = False}, formattedText = Nothing}
updateMemberCIsModerated :: MsgDirectionI d => DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> SMsgDirection d -> UTCTime -> IO ()
updateMemberCIsModerated db User {userId} GroupInfo {groupId, membership} member byGroupMember md deletedTs = do
itemIds <- updateCIs =<< getCurrentTime
DB.executeMany db deleteChatItemMessagesQuery itemIds
DB.executeMany db "DELETE FROM chat_item_versions WHERE chat_item_id = ?" itemIds
where
memId = groupMemberId' member
updateQuery =
[sql|
UPDATE chat_items
SET item_deleted = 1, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, item_content = ?, item_text = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
|]
updateCIs :: UTCTime -> IO [Only Int64]
updateCIs currentTs
| memId == groupMemberId' membership =
DB.query
db
(updateQuery <> " AND group_member_id IS NULL AND item_sent = 1 RETURNING chat_item_id")
(columns :. (userId, groupId))
| otherwise =
DB.query
db
(updateQuery <> " AND group_member_id = ? RETURNING chat_item_id")
(columns :. (userId, groupId, memId))
where
columns = (deletedTs, groupMemberId' byGroupMember, msgDirToModeratedContent_ md, ciModeratedText, currentTs)
updateGroupCIBlockedByAdmin :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup d -> UTCTime -> IO (ChatItem 'CTGroup d)
updateGroupCIBlockedByAdmin db User {userId} GroupInfo {groupId} ci deletedTs = do
currentTs <- getCurrentTime
@@ -2405,6 +2441,31 @@ markGroupChatItemDeleted db User {userId} GroupInfo {groupId} ci@ChatItem {meta}
(DBCIDeleted, deletedTs, deletedByGroupMemberId, currentTs, userId, groupId, itemId)
pure ci {meta = meta {itemDeleted, editable = False, deletable = False}}
markMemberCIsDeleted :: DB.Connection -> User -> GroupInfo -> GroupMember -> GroupMember -> UTCTime -> IO ()
markMemberCIsDeleted db User {userId} GroupInfo {groupId, membership} member byGroupMember deletedTs =
updateCIs =<< getCurrentTime
where
memId = groupMemberId' member
updateQuery =
[sql|
UPDATE chat_items
SET item_deleted = ?, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
|]
updateCIs currentTs
| memId == groupMemberId' membership =
DB.execute
db
(updateQuery <> " AND group_member_id IS NULL AND item_sent = 1")
(columns :. (userId, groupId))
| otherwise =
DB.execute
db
(updateQuery <> " AND group_member_id = ?")
(columns :. (userId, groupId, memId))
where
columns = (DBCIDeleted, deletedTs, groupMemberId' byGroupMember, currentTs)
markGroupChatItemBlocked :: DB.Connection -> User -> GroupInfo -> ChatItem 'CTGroup 'MDRcv -> IO (ChatItem 'CTGroup 'MDRcv)
markGroupChatItemBlocked db User {userId} GroupInfo {groupId} ci@ChatItem {meta} = do
deletedTs <- getCurrentTime
@@ -3314,6 +3314,22 @@ Query:
Plan:
SEARCH usage_conditions USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE chat_items
SET item_deleted = 1, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, item_content = ?, item_text = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
AND group_member_id = ? RETURNING chat_item_id
Plan:
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_shared_msg_id (user_id=? AND group_id=? AND group_member_id=?)
Query:
UPDATE chat_items
SET item_deleted = 1, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, item_content = ?, item_text = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
AND group_member_id IS NULL AND item_sent = 1 RETURNING chat_item_id
Plan:
SEARCH chat_items USING INDEX idx_chat_items_group_shared_msg_id (user_id=? AND group_id=? AND group_member_id=?)
Query:
UPDATE chat_items
SET item_deleted = 1, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, item_content = ?, item_text = ?, updated_at = ?
@@ -3322,6 +3338,22 @@ Query:
Plan:
SEARCH chat_items USING INTEGER PRIMARY KEY (rowid=?)
Query:
UPDATE chat_items
SET item_deleted = ?, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
AND group_member_id = ?
Plan:
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_shared_msg_id (user_id=? AND group_id=? AND group_member_id=?)
Query:
UPDATE chat_items
SET item_deleted = ?, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, updated_at = ?
WHERE user_id = ? AND group_id = ?
AND group_member_id IS NULL AND item_sent = 1
Plan:
SEARCH chat_items USING INDEX idx_chat_items_group_shared_msg_id (user_id=? AND group_id=? AND group_member_id=?)
Query:
UPDATE chat_items
SET item_deleted = ?, item_deleted_ts = ?, item_deleted_by_group_member_id = ?, updated_at = ?
@@ -3861,25 +3893,6 @@ LIST SUBQUERY 1
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
SEARCH groups USING COVERING INDEX idx_groups_group_profile_id (group_profile_id=?)
Query:
DELETE FROM messages
WHERE message_id IN (
SELECT message_id
FROM chat_item_messages
WHERE chat_item_id = ?
)
Plan:
SEARCH messages USING INTEGER PRIMARY KEY (rowid=?)
LIST SUBQUERY 1
SEARCH chat_item_messages USING COVERING INDEX sqlite_autoindex_chat_item_messages_2 (chat_item_id=?)
SEARCH msg_deliveries USING COVERING INDEX idx_msg_deliveries_message_id (message_id=?)
SEARCH chat_item_moderations USING COVERING INDEX idx_chat_item_moderations_created_by_msg_id (created_by_msg_id=?)
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_created_by_msg_id (created_by_msg_id=?)
SEARCH chat_item_messages USING COVERING INDEX sqlite_autoindex_chat_item_messages_1 (message_id=?)
SEARCH chat_items USING COVERING INDEX sqlite_autoindex_chat_items_1 (created_by_msg_id=?)
SEARCH pending_group_messages USING COVERING INDEX idx_pending_group_messages_message_id (message_id=?)
Query:
INSERT INTO calls
(contact_id, shared_call_id, call_uuid, chat_item_id, call_state, call_ts, user_id, created_at, updated_at)
@@ -4414,6 +4427,25 @@ Query:
Plan:
SEARCH xftp_file_descriptions USING INTEGER PRIMARY KEY (rowid=?)
Query:
DELETE FROM messages
WHERE message_id IN (
SELECT message_id
FROM chat_item_messages
WHERE chat_item_id = ?
)
Plan:
SEARCH messages USING INTEGER PRIMARY KEY (rowid=?)
LIST SUBQUERY 1
SEARCH chat_item_messages USING COVERING INDEX sqlite_autoindex_chat_item_messages_2 (chat_item_id=?)
SEARCH msg_deliveries USING COVERING INDEX idx_msg_deliveries_message_id (message_id=?)
SEARCH chat_item_moderations USING COVERING INDEX idx_chat_item_moderations_created_by_msg_id (created_by_msg_id=?)
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_created_by_msg_id (created_by_msg_id=?)
SEARCH chat_item_messages USING COVERING INDEX sqlite_autoindex_chat_item_messages_1 (message_id=?)
SEARCH chat_items USING COVERING INDEX sqlite_autoindex_chat_items_1 (created_by_msg_id=?)
SEARCH pending_group_messages USING COVERING INDEX idx_pending_group_messages_message_id (message_id=?)
Query:
SELECT
-- GroupInfo
@@ -4654,6 +4686,15 @@ Plan:
SEARCH i USING COVERING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?)
Query:
SELECT f.file_id, f.ci_file_status, f.file_path
FROM chat_items i
JOIN files f ON f.chat_item_id = i.chat_item_id
WHERE i.user_id = ? AND i.group_id = ? AND i.group_member_id = ?
Plan:
SEARCH i USING COVERING INDEX idx_chat_items_group_shared_msg_id (user_id=? AND group_id=? AND group_member_id=?)
SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?)
Query:
SELECT f.file_id, f.ci_file_status, f.file_path
FROM chat_items i