mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 20:29:53 +00:00
core: optimize group deletion (#5565)
* core: optimize group deletion * withFastStore * fix indexes * updated plans * remove prints * remove print * undo diff * core: optimize group delete - delayed group cleanup, delete unused contacts before deleting group (#5579) * core: delete unused group contacts, don't create new ones * remove from exceptions * plans * fix tests * remove fixtures * update plans * update plans * fix test * remove unused functino * update plans * remove withFastStore * core: time group deletion (#5596) * core: time group deletion * queries * works, test fails * fix * update plans * update migration, queries * not null * remove deleted --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> * cleanup * remove unused field * fix * fix * plans * fix plan save * plans --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
parent
1332480170
commit
9e000d6bce
18 changed files with 298 additions and 186 deletions
|
@ -1938,7 +1938,6 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
public var businessChat: BusinessChatInfo?
|
||||
public var fullGroupPreferences: FullGroupPreferences
|
||||
public var membership: GroupMember
|
||||
public var hostConnCustomUserProfileId: Int64?
|
||||
public var chatSettings: ChatSettings
|
||||
var createdAt: Date
|
||||
var updatedAt: Date
|
||||
|
@ -1974,7 +1973,6 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
|
|||
groupProfile: GroupProfile.sampleData,
|
||||
fullGroupPreferences: FullGroupPreferences.sampleData,
|
||||
membership: GroupMember.sampleData,
|
||||
hostConnCustomUserProfileId: nil,
|
||||
chatSettings: ChatSettings.defaults,
|
||||
createdAt: .now,
|
||||
updatedAt: .now,
|
||||
|
|
|
@ -1721,7 +1721,6 @@ data class GroupInfo (
|
|||
val businessChat: BusinessChatInfo? = null,
|
||||
val fullGroupPreferences: FullGroupPreferences,
|
||||
val membership: GroupMember,
|
||||
val hostConnCustomUserProfileId: Long? = null,
|
||||
val chatSettings: ChatSettings,
|
||||
override val createdAt: Instant,
|
||||
override val updatedAt: Instant,
|
||||
|
@ -1770,7 +1769,6 @@ data class GroupInfo (
|
|||
groupProfile = GroupProfile.sampleData,
|
||||
fullGroupPreferences = FullGroupPreferences.sampleData,
|
||||
membership = GroupMember.sampleData,
|
||||
hostConnCustomUserProfileId = null,
|
||||
chatSettings = ChatSettings(enableNtfs = MsgFilter.All, sendRcpts = null, favorite = false),
|
||||
createdAt = Clock.System.now(),
|
||||
updatedAt = Clock.System.now(),
|
||||
|
|
|
@ -223,6 +223,7 @@ library
|
|||
Simplex.Chat.Store.SQLite.Migrations.M20250122_chat_items_include_in_history
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250126_mentions
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250129_delete_unused_contacts
|
||||
Simplex.Chat.Store.SQLite.Migrations.M20250130_indexes
|
||||
other-modules:
|
||||
Paths_simplex_chat
|
||||
hs-source-dirs:
|
||||
|
|
|
@ -1076,12 +1076,12 @@ processChatCommand' vr = \case
|
|||
withFastStore' $ \db -> deletePendingContactConnection db userId chatId
|
||||
pure $ CRContactConnectionDeleted user conn
|
||||
CTGroup -> do
|
||||
Group gInfo@GroupInfo {membership} members <- withStore $ \db -> getGroup db vr user chatId
|
||||
Group gInfo@GroupInfo {membership} members <- withFastStore $ \db -> getGroup db vr user chatId
|
||||
let GroupMember {memberRole = membershipMemRole} = membership
|
||||
let isOwner = membershipMemRole == GROwner
|
||||
canDelete = isOwner || not (memberCurrent membership)
|
||||
unless canDelete $ throwChatError $ CEGroupUserRole gInfo GROwner
|
||||
filesInfo <- withStore' $ \db -> getGroupFileInfo db user gInfo
|
||||
filesInfo <- withFastStore' $ \db -> getGroupFileInfo db user gInfo
|
||||
withGroupLock "deleteChat group" chatId . procCmd $ do
|
||||
cancelFilesInProgress user filesInfo
|
||||
deleteFilesLocally filesInfo
|
||||
|
@ -1090,11 +1090,10 @@ processChatCommand' vr = \case
|
|||
deleteGroupLinkIfExists user gInfo
|
||||
deleteMembersConnections' user members doSendDel
|
||||
updateCIGroupInvitationStatus user gInfo CIGISRejected `catchChatError` \_ -> pure ()
|
||||
-- functions below are called in separate transactions to prevent crashes on android
|
||||
-- (possibly, race condition on integrity check?)
|
||||
withStore' $ \db -> deleteGroupConnectionsAndFiles db user gInfo members
|
||||
withStore' $ \db -> deleteGroupItemsAndMembers db user gInfo members
|
||||
withStore' $ \db -> deleteGroup db user gInfo
|
||||
withFastStore' $ \db -> deleteGroupChatItems db user gInfo
|
||||
withFastStore' $ \db -> cleanupHostGroupLinkConn db user gInfo
|
||||
withFastStore' $ \db -> deleteGroupMembers db user gInfo
|
||||
withFastStore' $ \db -> deleteGroup db user gInfo
|
||||
pure $ CRGroupDeletedUser user gInfo
|
||||
CTLocal -> pure $ chatCmdError (Just user) "not supported"
|
||||
CTContactRequest -> pure $ chatCmdError (Just user) "not supported"
|
||||
|
@ -3541,6 +3540,7 @@ cleanupManager = do
|
|||
cleanupUser cleanupInterval stepDelay user = do
|
||||
cleanupTimedItems cleanupInterval user `catchChatError` (toView . CRChatError (Just user))
|
||||
liftIO $ threadDelay' stepDelay
|
||||
-- TODO remove in future versions: legacy step - contacts are no longer marked as deleted
|
||||
cleanupDeletedContacts user `catchChatError` (toView . CRChatError (Just user))
|
||||
liftIO $ threadDelay' stepDelay
|
||||
cleanupTimedItems cleanupInterval user = do
|
||||
|
|
|
@ -61,6 +61,7 @@ import Simplex.Chat.Operators
|
|||
import Simplex.Chat.ProfileGenerator (generateRandomProfile)
|
||||
import Simplex.Chat.Protocol
|
||||
import Simplex.Chat.Store
|
||||
import Simplex.Chat.Store.Connections
|
||||
import Simplex.Chat.Store.Direct
|
||||
import Simplex.Chat.Store.Files
|
||||
import Simplex.Chat.Store.Groups
|
||||
|
@ -1200,11 +1201,9 @@ deleteMembersConnections user members = deleteMembersConnections' user members F
|
|||
|
||||
deleteMembersConnections' :: User -> [GroupMember] -> Bool -> CM ()
|
||||
deleteMembersConnections' user members waitDelivery = do
|
||||
let memberConns =
|
||||
filter (\Connection {connStatus} -> connStatus /= ConnDeleted) $
|
||||
mapMaybe (\GroupMember {activeConn} -> activeConn) members
|
||||
let memberConns = mapMaybe (\GroupMember {activeConn} -> activeConn) members
|
||||
deleteAgentConnectionsAsync' user (map aConnId memberConns) waitDelivery
|
||||
lift . void . withStoreBatch' $ \db -> map (\conn -> updateConnectionStatus db conn ConnDeleted) memberConns
|
||||
lift . void . withStoreBatch' $ \db -> map (\Connection {connId} -> deleteConnectionRecord db user connId) memberConns
|
||||
|
||||
deleteMemberConnection :: User -> GroupMember -> CM ()
|
||||
deleteMemberConnection user mem = deleteMemberConnection' user mem False
|
||||
|
|
|
@ -134,7 +134,7 @@ getConnectionEntity db vr user@User {userId, userContactId} agentConnId = do
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
|
|
@ -35,7 +35,6 @@ module Simplex.Chat.Store.Direct
|
|||
deleteContactFiles,
|
||||
deleteContact,
|
||||
deleteContactWithoutGroups,
|
||||
setContactDeleted,
|
||||
getDeletedContacts,
|
||||
getContactByName,
|
||||
getContact,
|
||||
|
@ -294,7 +293,7 @@ deleteContact db user@User {userId} ct@Contact {contactId, localDisplayName, act
|
|||
assertNotUser db user ct
|
||||
liftIO $ do
|
||||
DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND contact_id = ?" (userId, contactId)
|
||||
ctMember :: (Maybe ContactId) <- maybeFirstRow fromOnly $ DB.query db "SELECT contact_id FROM group_members WHERE user_id = ? AND contact_id = ? LIMIT 1" (userId, contactId)
|
||||
ctMember :: (Maybe ContactId) <- maybeFirstRow fromOnly $ DB.query db "SELECT contact_id FROM group_members WHERE contact_id = ? LIMIT 1" (Only contactId)
|
||||
if isNothing ctMember
|
||||
then do
|
||||
deleteContactProfile_ db userId contactId
|
||||
|
@ -322,13 +321,7 @@ deleteContactWithoutGroups db user@User {userId} ct@Contact {contactId, localDis
|
|||
forM_ customUserProfileId $ \profileId ->
|
||||
deleteUnusedIncognitoProfileById_ db user profileId
|
||||
|
||||
setContactDeleted :: DB.Connection -> User -> Contact -> ExceptT StoreError IO ()
|
||||
setContactDeleted db user@User {userId} ct@Contact {contactId} = do
|
||||
assertNotUser db user ct
|
||||
liftIO $ do
|
||||
currentTs <- getCurrentTime
|
||||
DB.execute db "UPDATE contacts SET deleted = 1, updated_at = ? WHERE user_id = ? AND contact_id = ?" (currentTs, userId, contactId)
|
||||
|
||||
-- TODO remove in future versions: only used for legacy contact cleanup
|
||||
getDeletedContacts :: DB.Connection -> VersionRangeChat -> User -> IO [Contact]
|
||||
getDeletedContacts db vr user@User {userId} = do
|
||||
contactIds <- map fromOnly <$> DB.query db "SELECT contact_id FROM contacts WHERE user_id = ? AND deleted = 1" (Only userId)
|
||||
|
|
|
@ -55,16 +55,15 @@ module Simplex.Chat.Store.Groups
|
|||
getGroupModerators,
|
||||
getGroupMembersForExpiration,
|
||||
getGroupCurrentMembersCount,
|
||||
deleteGroupConnectionsAndFiles,
|
||||
deleteGroupItemsAndMembers,
|
||||
deleteGroupChatItems,
|
||||
deleteGroupMembers,
|
||||
cleanupHostGroupLinkConn,
|
||||
deleteGroup,
|
||||
getUserGroups,
|
||||
getUserGroupsToSubscribe,
|
||||
getUserGroupDetails,
|
||||
getUserGroupsWithSummary,
|
||||
getGroupSummary,
|
||||
getContactGroupPreferences,
|
||||
checkContactHasGroups,
|
||||
getGroupInvitation,
|
||||
createNewContactMember,
|
||||
createNewContactMemberAsync,
|
||||
|
@ -275,7 +274,7 @@ getGroupAndMember db User {userId, userContactId} groupMemberId vr = do
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
@ -347,7 +346,6 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc
|
|||
businessChat = Nothing,
|
||||
fullGroupPreferences,
|
||||
membership,
|
||||
hostConnCustomUserProfileId = Nothing,
|
||||
chatSettings,
|
||||
createdAt = currentTs,
|
||||
updatedAt = currentTs,
|
||||
|
@ -362,7 +360,7 @@ createNewGroup db vr gVar user@User {userId} groupProfile incognitoProfile = Exc
|
|||
-- | creates a new group record for the group the current user was invited to, or returns an existing one
|
||||
createGroupInvitation :: DB.Connection -> VersionRangeChat -> User -> Contact -> GroupInvitation -> Maybe ProfileId -> ExceptT StoreError IO (GroupInfo, GroupMemberId)
|
||||
createGroupInvitation _ _ _ Contact {localDisplayName, activeConn = Nothing} _ _ = throwError $ SEContactNotReady localDisplayName
|
||||
createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activeConn = Just Connection {customUserProfileId, peerChatVRange}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile, business} incognitoProfileId = do
|
||||
createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activeConn = Just Connection {peerChatVRange}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile, business} incognitoProfileId = do
|
||||
liftIO getInvitationGroupId_ >>= \case
|
||||
Nothing -> createGroupInvitation_
|
||||
Just gId -> do
|
||||
|
@ -399,11 +397,11 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
|
|||
db
|
||||
[sql|
|
||||
INSERT INTO groups
|
||||
(group_profile_id, local_display_name, inv_queue_info, host_conn_custom_user_profile_id, user_id, enable_ntfs,
|
||||
(group_profile_id, local_display_name, inv_queue_info, user_id, enable_ntfs,
|
||||
created_at, updated_at, chat_ts, user_member_profile_sent_at, business_chat, business_member_id, customer_member_id)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
((profileId, localDisplayName, connRequest, customUserProfileId, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. businessChatInfoRow business)
|
||||
((profileId, localDisplayName, connRequest, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. businessChatInfoRow business)
|
||||
insertedRowId db
|
||||
let hostVRange = adjustedMemberVRange vr peerChatVRange
|
||||
GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId Nothing contact fromMember GCHostMember GSMemInvited IBUnknown Nothing currentTs hostVRange
|
||||
|
@ -418,7 +416,6 @@ createGroupInvitation db vr user@User {userId} contact@Contact {contactId, activ
|
|||
businessChat = Nothing,
|
||||
fullGroupPreferences,
|
||||
membership,
|
||||
hostConnCustomUserProfileId = customUserProfileId,
|
||||
chatSettings,
|
||||
createdAt = currentTs,
|
||||
updatedAt = currentTs,
|
||||
|
@ -546,11 +543,11 @@ createGroupInvitedViaLink
|
|||
db
|
||||
[sql|
|
||||
INSERT INTO groups
|
||||
(group_profile_id, local_display_name, host_conn_custom_user_profile_id, user_id, enable_ntfs,
|
||||
(group_profile_id, local_display_name, user_id, enable_ntfs,
|
||||
created_at, updated_at, chat_ts, user_member_profile_sent_at, business_chat, business_member_id, customer_member_id)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
((profileId, localDisplayName, customUserProfileId, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. businessChatInfoRow business)
|
||||
((profileId, localDisplayName, userId, BI True, currentTs, currentTs, currentTs, currentTs) :. businessChatInfoRow business)
|
||||
insertedRowId db
|
||||
insertHost_ currentTs groupId = do
|
||||
let fromMemberProfile = profileFromName fromMemberName
|
||||
|
@ -639,33 +636,75 @@ getGroupToSubscribe db User {userId, userContactId} groupId = do
|
|||
toShortMember (groupMemberId, localDisplayName, agentConnId) =
|
||||
ShortGroupMember groupMemberId groupId localDisplayName agentConnId
|
||||
|
||||
deleteGroupConnectionsAndFiles :: DB.Connection -> User -> GroupInfo -> [GroupMember] -> IO ()
|
||||
deleteGroupConnectionsAndFiles db User {userId} GroupInfo {groupId} members = do
|
||||
forM_ members $ \m -> DB.execute db "DELETE FROM connections WHERE user_id = ? AND group_member_id = ?" (userId, groupMemberId' m)
|
||||
DB.execute db "DELETE FROM files WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
|
||||
deleteGroupItemsAndMembers :: DB.Connection -> User -> GroupInfo -> [GroupMember] -> IO ()
|
||||
deleteGroupItemsAndMembers db user@User {userId} g@GroupInfo {groupId} members = do
|
||||
deleteGroupChatItems :: DB.Connection -> User -> GroupInfo -> IO ()
|
||||
deleteGroupChatItems db User {userId} GroupInfo {groupId} =
|
||||
DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
void $ runExceptT cleanupHostGroupLinkConn_ -- to allow repeat connection via the same group link if one was used
|
||||
|
||||
deleteGroupMembers :: DB.Connection -> User -> GroupInfo -> IO ()
|
||||
deleteGroupMembers db User {userId} GroupInfo {groupId} = do
|
||||
DB.execute_ db "DROP TABLE IF EXISTS temp_delete_members"
|
||||
#if defined(dbPostgres)
|
||||
DB.execute_ db "CREATE TABLE temp_delete_members (contact_profile_id BIGINT, member_profile_id BIGINT, local_display_name TEXT)"
|
||||
#else
|
||||
DB.execute_ db "CREATE TABLE temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)"
|
||||
#endif
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
INSERT INTO temp_delete_members (contact_profile_id, member_profile_id, local_display_name)
|
||||
SELECT contact_profile_id, member_profile_id, local_display_name FROM group_members WHERE group_id = ?
|
||||
|]
|
||||
(Only groupId)
|
||||
DB.execute db "DELETE FROM group_members WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
forM_ members $ cleanupMemberProfileAndName_ db user
|
||||
forM_ (incognitoMembershipProfile g) $ deleteUnusedIncognitoProfileById_ db user . localProfileId
|
||||
where
|
||||
cleanupHostGroupLinkConn_ = do
|
||||
hostId <- getHostMemberId_ db user groupId
|
||||
liftIO $
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
WHERE user_id = ? AND group_member_id = ?
|
||||
)
|
||||
|]
|
||||
(userId, userId, hostId)
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
DELETE FROM contact_profiles
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND (contact_profile_id IN (SELECT contact_profile_id FROM temp_delete_members)
|
||||
OR contact_profile_id IN (SELECT member_profile_id FROM temp_delete_members WHERE member_profile_id IS NOT NULL))
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT member_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contacts)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contact_requests)
|
||||
AND contact_profile_id NOT IN (SELECT custom_user_profile_id FROM connections)
|
||||
|]
|
||||
(Only userId)
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
DELETE FROM display_names
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND local_display_name IN (SELECT local_display_name FROM temp_delete_members)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM group_members)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM contacts)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM users)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM groups)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM user_contact_links)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM contact_requests)
|
||||
|]
|
||||
(Only userId)
|
||||
DB.execute_ db "DROP TABLE temp_delete_members"
|
||||
|
||||
-- to allow repeat connection via the same group link if one was used
|
||||
cleanupHostGroupLinkConn :: DB.Connection -> User -> GroupInfo -> IO ()
|
||||
cleanupHostGroupLinkConn db user@User {userId} GroupInfo {groupId} = do
|
||||
runExceptT (getHostMemberId_ db user groupId) >>= \case
|
||||
Left _ -> pure ()
|
||||
Right hostId ->
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
WHERE user_id = ? AND group_member_id = ?
|
||||
)
|
||||
|]
|
||||
(userId, userId, hostId)
|
||||
|
||||
deleteGroup :: DB.Connection -> User -> GroupInfo -> IO ()
|
||||
deleteGroup db user@User {userId} g@GroupInfo {groupId, localDisplayName} = do
|
||||
|
@ -688,11 +727,6 @@ deleteGroupProfile_ db userId groupId =
|
|||
|]
|
||||
(userId, groupId)
|
||||
|
||||
getUserGroups :: DB.Connection -> VersionRangeChat -> User -> IO [Group]
|
||||
getUserGroups db vr user@User {userId} = do
|
||||
groupIds <- map fromOnly <$> DB.query db "SELECT group_id FROM groups WHERE user_id = ?" (Only userId)
|
||||
rights <$> mapM (runExceptT . getGroup db vr user) groupIds
|
||||
|
||||
getUserGroupsToSubscribe :: DB.Connection -> User -> IO [ShortGroup]
|
||||
getUserGroupsToSubscribe db user@User {userId} = do
|
||||
groupIds <- map fromOnly <$> DB.query db "SELECT group_id FROM groups WHERE user_id = ?" (Only userId)
|
||||
|
@ -707,7 +741,7 @@ getUserGroupDetails db vr User {userId, userContactId} _contactId_ search_ = do
|
|||
[sql|
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
|
||||
|
@ -763,10 +797,6 @@ getContactGroupPreferences db User {userId} Contact {contactId} = do
|
|||
|]
|
||||
(userId, contactId)
|
||||
|
||||
checkContactHasGroups :: DB.Connection -> User -> Contact -> IO (Maybe GroupId)
|
||||
checkContactHasGroups db User {userId} Contact {contactId} =
|
||||
maybeFirstRow fromOnly $ DB.query db "SELECT group_id FROM group_members WHERE user_id = ? AND contact_id = ? LIMIT 1" (userId, contactId)
|
||||
|
||||
getGroupInfoByName :: DB.Connection -> VersionRangeChat -> User -> GroupName -> ExceptT StoreError IO GroupInfo
|
||||
getGroupInfoByName db vr user gName = do
|
||||
gId <- getGroupIdByName db user gName
|
||||
|
@ -801,19 +831,21 @@ getGroupMember db vr user@User {userId} groupId groupMemberId =
|
|||
|
||||
getMentionedGroupMember :: DB.Connection -> User -> GroupId -> GroupMemberId -> ExceptT StoreError IO CIMention
|
||||
getMentionedGroupMember db User {userId} groupId gmId =
|
||||
ExceptT $ firstRow toMentionedMember (SEGroupMemberNotFound gmId) $
|
||||
DB.query
|
||||
db
|
||||
(mentionedMemberQuery <> " WHERE m.group_id = ? AND m.group_member_id = ? AND m.user_id = ?")
|
||||
(groupId, gmId, userId)
|
||||
ExceptT $
|
||||
firstRow toMentionedMember (SEGroupMemberNotFound gmId) $
|
||||
DB.query
|
||||
db
|
||||
(mentionedMemberQuery <> " WHERE m.group_id = ? AND m.group_member_id = ? AND m.user_id = ?")
|
||||
(groupId, gmId, userId)
|
||||
|
||||
getMentionedMemberByMemberId :: DB.Connection -> User -> GroupId -> MsgMention -> IO CIMention
|
||||
getMentionedMemberByMemberId db User {userId} groupId MsgMention {memberId} =
|
||||
fmap (fromMaybe mentionedMember) $ maybeFirstRow toMentionedMember $
|
||||
DB.query
|
||||
db
|
||||
(mentionedMemberQuery <> " WHERE m.group_id = ? AND m.member_id = ? AND m.user_id = ?")
|
||||
(groupId, memberId, userId)
|
||||
fmap (fromMaybe mentionedMember) $
|
||||
maybeFirstRow toMentionedMember $
|
||||
DB.query
|
||||
db
|
||||
(mentionedMemberQuery <> " WHERE m.group_id = ? AND m.member_id = ? AND m.user_id = ?")
|
||||
(groupId, memberId, userId)
|
||||
where
|
||||
mentionedMember = CIMention {memberId, memberRef = Nothing}
|
||||
|
||||
|
@ -1470,7 +1502,7 @@ getViaGroupMember db vr User {userId, userContactId} Contact {contactId} = do
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
|
|
@ -128,7 +128,6 @@ CREATE TABLE groups(
|
|||
updated_at TIMESTAMPTZ NOT NULL,
|
||||
chat_item_id BIGINT DEFAULT NULL,
|
||||
enable_ntfs SMALLINT,
|
||||
host_conn_custom_user_profile_id BIGINT REFERENCES contact_profiles ON DELETE SET NULL,
|
||||
unread_chat SMALLINT NOT NULL DEFAULT 0,
|
||||
chat_ts TIMESTAMPTZ,
|
||||
favorite SMALLINT NOT NULL DEFAULT 0,
|
||||
|
@ -692,7 +691,6 @@ CREATE INDEX idx_groups_inv_queue_info ON groups(inv_queue_info);
|
|||
CREATE INDEX idx_contact_requests_xcontact_id ON contact_requests(xcontact_id);
|
||||
CREATE INDEX idx_contacts_xcontact_id ON contacts(xcontact_id);
|
||||
CREATE INDEX idx_messages_shared_msg_id ON messages(shared_msg_id);
|
||||
CREATE INDEX idx_chat_items_shared_msg_id ON chat_items(shared_msg_id);
|
||||
CREATE UNIQUE INDEX idx_chat_items_direct_shared_msg_id ON chat_items(
|
||||
user_id,
|
||||
contact_id,
|
||||
|
@ -765,9 +763,6 @@ CREATE INDEX idx_group_members_contact_profile_id ON group_members(
|
|||
CREATE INDEX idx_group_members_user_id ON group_members(user_id);
|
||||
CREATE INDEX idx_group_members_invited_by ON group_members(invited_by);
|
||||
CREATE INDEX idx_group_profiles_user_id ON group_profiles(user_id);
|
||||
CREATE INDEX idx_groups_host_conn_custom_user_profile_id ON groups(
|
||||
host_conn_custom_user_profile_id
|
||||
);
|
||||
CREATE INDEX idx_groups_chat_item_id ON groups(chat_item_id);
|
||||
CREATE INDEX idx_groups_group_profile_id ON groups(group_profile_id);
|
||||
CREATE INDEX idx_messages_group_id ON messages(group_id);
|
||||
|
@ -1034,7 +1029,27 @@ CREATE INDEX idx_group_snd_item_statuses_chat_item_id_group_member_id ON group_s
|
|||
group_member_id
|
||||
);
|
||||
CREATE INDEX idx_chat_item_mentions_group_id ON chat_item_mentions(group_id);
|
||||
CREATE INDEX idx_chat_item_mentions_chat_item_id ON chat_item_mentions(chat_item_id);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_display_name ON chat_item_mentions(chat_item_id, display_name);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_member_id ON chat_item_mentions(chat_item_id, member_id);
|
||||
CREATE INDEX idx_chat_item_mentions_chat_item_id ON chat_item_mentions(
|
||||
chat_item_id
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_display_name ON chat_item_mentions(
|
||||
chat_item_id,
|
||||
display_name
|
||||
);
|
||||
CREATE UNIQUE INDEX idx_chat_item_mentions_member_id ON chat_item_mentions(
|
||||
chat_item_id,
|
||||
member_id
|
||||
);
|
||||
CREATE INDEX idx_chat_items_groups_user_mention ON chat_items(
|
||||
user_id,
|
||||
group_id,
|
||||
item_status,
|
||||
user_mention
|
||||
);
|
||||
CREATE INDEX idx_chat_items_group_id ON chat_items(group_id);
|
||||
CREATE INDEX idx_connections_group_member_id ON connections(group_member_id);
|
||||
CREATE INDEX idx_chat_items_group_id_shared_msg_id ON chat_items(
|
||||
group_id,
|
||||
shared_msg_id
|
||||
);
|
||||
|]
|
||||
|
|
|
@ -127,6 +127,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20250115_chat_ttl
|
|||
import Simplex.Chat.Store.SQLite.Migrations.M20250122_chat_items_include_in_history
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250126_mentions
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250129_delete_unused_contacts
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20250130_indexes
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||
|
@ -253,7 +254,8 @@ schemaMigrations =
|
|||
("20250115_chat_ttl", m20250115_chat_ttl, Just down_m20250115_chat_ttl),
|
||||
("20250122_chat_items_include_in_history", m20250122_chat_items_include_in_history, Just down_m20250122_chat_items_include_in_history),
|
||||
("20250126_mentions", m20250126_mentions, Just down_m20250126_mentions),
|
||||
("20250129_delete_unused_contacts", m20250129_delete_unused_contacts, Just down_m20250129_delete_unused_contacts)
|
||||
("20250129_delete_unused_contacts", m20250129_delete_unused_contacts, Just down_m20250129_delete_unused_contacts),
|
||||
("20250130_indexes", m20250130_indexes, Just down_m20250130_indexes)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
|
|
@ -43,12 +43,14 @@ WHERE
|
|||
OR contact_profile_id IN (SELECT contact_profile_id FROM temp_delete_contacts))
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT member_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contacts)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contact_requests)
|
||||
AND contact_profile_id NOT IN (SELECT custom_user_profile_id FROM connections);
|
||||
|
||||
DELETE FROM display_names
|
||||
WHERE local_display_name IN (SELECT local_display_name FROM temp_delete_contacts)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM group_members)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM contacts)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM users)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM groups)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM user_contact_links)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.SQLite.Migrations.M20250130_indexes where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20250130_indexes :: Query
|
||||
m20250130_indexes =
|
||||
[sql|
|
||||
CREATE INDEX idx_chat_items_group_id ON chat_items(group_id);
|
||||
|
||||
CREATE INDEX idx_connections_group_member_id ON connections(group_member_id);
|
||||
|
||||
DROP INDEX idx_chat_items_shared_msg_id;
|
||||
CREATE INDEX idx_chat_items_group_id_shared_msg_id ON chat_items(group_id, shared_msg_id);
|
||||
|
||||
|
||||
DROP INDEX idx_groups_host_conn_custom_user_profile_id;
|
||||
ALTER TABLE groups DROP COLUMN host_conn_custom_user_profile_id;
|
||||
|]
|
||||
|
||||
down_m20250130_indexes :: Query
|
||||
down_m20250130_indexes =
|
||||
[sql|
|
||||
ALTER TABLE groups ADD COLUMN host_conn_custom_user_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL;
|
||||
CREATE INDEX idx_groups_host_conn_custom_user_profile_id ON groups(host_conn_custom_user_profile_id);
|
||||
|
||||
|
||||
DROP INDEX idx_chat_items_group_id_shared_msg_id;
|
||||
CREATE INDEX idx_chat_items_shared_msg_id ON chat_items(shared_msg_id);
|
||||
|
||||
DROP INDEX idx_connections_group_member_id;
|
||||
|
||||
DROP INDEX idx_chat_items_group_id;
|
||||
|]
|
|
@ -1,2 +0,0 @@
|
|||
CREATE INDEX 'chat_items_group_id' ON 'chat_items'('group_id'); --> groups(group_id)
|
||||
CREATE INDEX 'connections_group_member_id' ON 'connections'('group_member_id'); --> group_members(group_member_id)
|
|
@ -9,7 +9,7 @@ Plan:
|
|||
|
||||
Query:
|
||||
INSERT INTO groups
|
||||
(group_profile_id, local_display_name, host_conn_custom_user_profile_id, user_id, enable_ntfs,
|
||||
(group_profile_id, local_display_name, inv_queue_info, user_id, enable_ntfs,
|
||||
created_at, updated_at, chat_ts, user_member_profile_sent_at, business_chat, business_member_id, customer_member_id)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|
||||
|
@ -17,9 +17,9 @@ Plan:
|
|||
|
||||
Query:
|
||||
INSERT INTO groups
|
||||
(group_profile_id, local_display_name, inv_queue_info, host_conn_custom_user_profile_id, user_id, enable_ntfs,
|
||||
(group_profile_id, local_display_name, user_id, enable_ntfs,
|
||||
created_at, updated_at, chat_ts, user_member_profile_sent_at, business_chat, business_member_id, customer_member_id)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?)
|
||||
|
||||
Plan:
|
||||
|
||||
|
@ -35,7 +35,7 @@ Query:
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
@ -605,19 +605,6 @@ SEARCH m USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
|||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH h USING INDEX idx_sent_probe_hashes_sent_probe_id (sent_probe_id=?)
|
||||
|
||||
Query:
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
WHERE user_id = ? AND group_member_id = ?
|
||||
)
|
||||
|
||||
Plan:
|
||||
SEARCH connections USING INDEX idx_connections_updated_at (user_id=?)
|
||||
LIST SUBQUERY 1
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM chat_item_reactions
|
||||
WHERE contact_id = ? AND shared_msg_id = ? AND reaction_sent = ? AND reaction = ?
|
||||
|
@ -742,7 +729,7 @@ SEARCH i USING INTEGER PRIMARY KEY (rowid=?)
|
|||
SEARCH f USING INDEX idx_files_chat_item_id (chat_item_id=?) LEFT-JOIN
|
||||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH ri USING INDEX idx_chat_items_shared_msg_id (shared_msg_id=?) LEFT-JOIN
|
||||
SEARCH ri USING INDEX idx_chat_items_group_id_shared_msg_id (group_id=? AND shared_msg_id=?) LEFT-JOIN
|
||||
SEARCH rm USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH rp USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH dbm USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
|
@ -795,7 +782,7 @@ Query:
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
@ -838,7 +825,7 @@ SEARCH cc USING COVERING INDEX idx_connections_group_member (user_id=? AND group
|
|||
Query:
|
||||
SELECT
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction,
|
||||
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
|
||||
|
@ -951,7 +938,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_group_member_id (group_member_id=?)
|
||||
SEARCH chat_items USING INDEX idx_chat_items_group_id (group_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id
|
||||
|
@ -961,8 +948,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
SEARCH chat_items USING INDEX idx_chat_items_group_id (group_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id, contact_id, group_id, note_folder_id
|
||||
|
@ -1115,7 +1101,7 @@ Query:
|
|||
|
||||
Plan:
|
||||
SEARCH m USING INDEX sqlite_autoindex_group_members_1 (group_id=? AND member_id=?)
|
||||
SEARCH i USING INDEX idx_chat_items_shared_msg_id (shared_msg_id=?)
|
||||
SEARCH i USING INDEX idx_chat_items_group_id_shared_msg_id (group_id=? AND shared_msg_id=?)
|
||||
|
||||
Query:
|
||||
SELECT i.chat_item_id
|
||||
|
@ -1126,9 +1112,8 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH i USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
SEARCH i USING INDEX idx_chat_items_group_id (group_id=?)
|
||||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
SELECT i.chat_item_id, i.contact_id, i.group_id, i.note_folder_id
|
||||
|
@ -1193,6 +1178,19 @@ SEARCH r USING INDEX idx_received_probes_user_id (user_id=?)
|
|||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
|
||||
Query:
|
||||
UPDATE connections SET via_contact_uri_hash = NULL, xcontact_id = NULL
|
||||
WHERE user_id = ? AND via_group_link = 1 AND contact_id IN (
|
||||
SELECT contact_id
|
||||
FROM group_members
|
||||
WHERE user_id = ? AND group_member_id = ?
|
||||
)
|
||||
|
||||
Plan:
|
||||
SEARCH connections USING INDEX idx_connections_updated_at (user_id=?)
|
||||
LIST SUBQUERY 1
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE contacts
|
||||
SET local_display_name = ?, contact_profile_id = ?, updated_at = ?
|
||||
|
@ -2847,8 +2845,7 @@ Query:
|
|||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH chat_items USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
SEARCH chat_items USING INDEX idx_chat_items_group_id (group_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id
|
||||
|
@ -3475,6 +3472,35 @@ SEARCH commands USING COVERING INDEX idx_commands_connection_id (connection_id=?
|
|||
SEARCH messages USING COVERING INDEX idx_messages_connection_id (connection_id=?)
|
||||
SEARCH snd_files USING COVERING INDEX idx_snd_files_connection_id (connection_id=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM contact_profiles
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND (contact_profile_id IN (SELECT contact_profile_id FROM temp_delete_members)
|
||||
OR contact_profile_id IN (SELECT member_profile_id FROM temp_delete_members WHERE member_profile_id IS NOT NULL))
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT member_profile_id FROM group_members)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contacts)
|
||||
AND contact_profile_id NOT IN (SELECT contact_profile_id FROM contact_requests)
|
||||
AND contact_profile_id NOT IN (SELECT custom_user_profile_id FROM connections)
|
||||
|
||||
Plan:
|
||||
SEARCH contact_profiles USING COVERING INDEX idx_contact_profiles_user_id (user_id=?)
|
||||
LIST SUBQUERY 1
|
||||
SCAN temp_delete_members
|
||||
LIST SUBQUERY 2
|
||||
SCAN temp_delete_members
|
||||
USING INDEX idx_group_members_contact_profile_id FOR IN-OPERATOR
|
||||
USING INDEX idx_group_members_member_profile_id FOR IN-OPERATOR
|
||||
USING INDEX idx_contacts_contact_profile_id FOR IN-OPERATOR
|
||||
USING INDEX idx_contact_requests_contact_profile_id FOR IN-OPERATOR
|
||||
USING INDEX idx_connections_custom_user_profile_id FOR IN-OPERATOR
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM contact_profiles
|
||||
WHERE contact_profile_id in (
|
||||
|
@ -3491,7 +3517,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3510,7 +3535,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3531,7 +3555,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3552,7 +3575,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3591,7 +3613,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3604,7 +3625,6 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
|
@ -3629,9 +3649,41 @@ SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profil
|
|||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM display_names
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND local_display_name IN (SELECT local_display_name FROM temp_delete_members)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM group_members)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM contacts)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM users)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM groups)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM user_contact_links)
|
||||
AND local_display_name NOT IN (SELECT local_display_name FROM contact_requests)
|
||||
|
||||
Plan:
|
||||
SEARCH display_names USING PRIMARY KEY (user_id=? AND local_display_name=?)
|
||||
LIST SUBQUERY 1
|
||||
SCAN temp_delete_members
|
||||
LIST SUBQUERY 2
|
||||
SCAN group_members USING COVERING INDEX idx_group_members_user_id_local_display_name
|
||||
LIST SUBQUERY 3
|
||||
SCAN contacts USING COVERING INDEX sqlite_autoindex_contacts_1
|
||||
USING INDEX sqlite_autoindex_users_2 FOR IN-OPERATOR
|
||||
LIST SUBQUERY 5
|
||||
SCAN groups USING COVERING INDEX sqlite_autoindex_groups_1
|
||||
LIST SUBQUERY 6
|
||||
SCAN user_contact_links USING COVERING INDEX sqlite_autoindex_user_contact_links_1
|
||||
LIST SUBQUERY 7
|
||||
SCAN contact_requests USING COVERING INDEX sqlite_autoindex_contact_requests_1
|
||||
SEARCH contact_requests USING COVERING INDEX sqlite_autoindex_contact_requests_1 (user_id=? AND local_display_name=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_user_id_local_display_name (user_id=? AND local_display_name=?)
|
||||
SEARCH groups USING COVERING INDEX sqlite_autoindex_groups_1 (user_id=? AND local_display_name=?)
|
||||
SEARCH contacts USING COVERING INDEX sqlite_autoindex_contacts_1 (user_id=? AND local_display_name=?)
|
||||
SEARCH users USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
DELETE FROM display_names
|
||||
WHERE user_id = ?
|
||||
|
@ -3931,6 +3983,13 @@ Query:
|
|||
|
||||
Plan:
|
||||
|
||||
Query:
|
||||
INSERT INTO temp_delete_members (contact_profile_id, member_profile_id, local_display_name)
|
||||
SELECT contact_profile_id, member_profile_id, local_display_name FROM group_members WHERE group_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id, timed_ttl
|
||||
FROM chat_items
|
||||
|
@ -4341,7 +4400,7 @@ Query:
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
@ -4362,7 +4421,7 @@ Query:
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
@ -4817,6 +4876,9 @@ SEARCH chat_items USING COVERING INDEX idx_chat_items_groups_item_ts (user_id=?
|
|||
Query: CREATE TABLE temp_conn_ids (conn_id BLOB)
|
||||
Error: SQLite3 returned ErrorError while attempting to perform prepare "explain query plan CREATE TABLE temp_conn_ids (conn_id BLOB)": table temp_conn_ids already exists
|
||||
|
||||
Query: CREATE TABLE temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)
|
||||
Error: SQLite3 returned ErrorError while attempting to perform prepare "explain query plan CREATE TABLE temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)": table temp_delete_members already exists
|
||||
|
||||
Query: DELETE FROM app_settings
|
||||
Plan:
|
||||
|
||||
|
@ -4932,16 +4994,6 @@ SEARCH commands USING COVERING INDEX idx_commands_connection_id (connection_id=?
|
|||
SEARCH messages USING COVERING INDEX idx_messages_connection_id (connection_id=?)
|
||||
SEARCH snd_files USING COVERING INDEX idx_snd_files_connection_id (connection_id=?)
|
||||
|
||||
Query: DELETE FROM contact_profiles WHERE user_id = ? AND contact_profile_id = ?
|
||||
Plan:
|
||||
SEARCH contact_profiles USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_custom_user_profile_id (custom_user_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_member_profile_id (member_profile_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_profile_id (contact_profile_id=?)
|
||||
SEARCH groups USING COVERING INDEX idx_groups_host_conn_custom_user_profile_id (host_conn_custom_user_profile_id=?)
|
||||
SEARCH contacts USING COVERING INDEX idx_contacts_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query: DELETE FROM contact_requests WHERE user_id = ? AND contact_request_id = ?
|
||||
Plan:
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
@ -4982,14 +5034,6 @@ SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?)
|
|||
SEARCH snd_files USING COVERING INDEX idx_snd_files_file_id (file_id=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_redirect_file_id (redirect_file_id=?)
|
||||
|
||||
Query: DELETE FROM files WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH files USING INDEX idx_files_group_id (group_id=?)
|
||||
SEARCH extra_xftp_file_descriptions USING COVERING INDEX idx_extra_xftp_file_descriptions_file_id (file_id=?)
|
||||
SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH snd_files USING COVERING INDEX idx_snd_files_file_id (file_id=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_redirect_file_id (redirect_file_id=?)
|
||||
|
||||
Query: DELETE FROM group_members WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_group_id (user_id=? AND group_id=?)
|
||||
|
@ -5005,7 +5049,7 @@ SEARCH chat_items USING COVERING INDEX idx_chat_items_group_member_id (group_mem
|
|||
SEARCH pending_group_messages USING COVERING INDEX idx_pending_group_messages_group_member_id (group_member_id=?)
|
||||
SEARCH messages USING COVERING INDEX idx_messages_forwarded_by_group_member_id (forwarded_by_group_member_id=?)
|
||||
SEARCH messages USING COVERING INDEX idx_messages_author_group_member_id (author_group_member_id=?)
|
||||
SCAN connections USING COVERING INDEX idx_connections_group_member
|
||||
SEARCH connections USING COVERING INDEX idx_connections_group_member_id (group_member_id=?)
|
||||
SEARCH rcv_files USING COVERING INDEX idx_rcv_files_group_member_id (group_member_id=?)
|
||||
SEARCH snd_files USING COVERING INDEX idx_snd_files_group_member_id (group_member_id=?)
|
||||
SEARCH group_member_intros USING COVERING INDEX idx_group_member_intros_to_group_member_id (to_group_member_id=?)
|
||||
|
@ -5028,7 +5072,7 @@ SEARCH chat_items USING COVERING INDEX idx_chat_items_group_member_id (group_mem
|
|||
SEARCH pending_group_messages USING COVERING INDEX idx_pending_group_messages_group_member_id (group_member_id=?)
|
||||
SEARCH messages USING COVERING INDEX idx_messages_forwarded_by_group_member_id (forwarded_by_group_member_id=?)
|
||||
SEARCH messages USING COVERING INDEX idx_messages_author_group_member_id (author_group_member_id=?)
|
||||
SCAN connections USING COVERING INDEX idx_connections_group_member
|
||||
SEARCH connections USING COVERING INDEX idx_connections_group_member_id (group_member_id=?)
|
||||
SEARCH rcv_files USING COVERING INDEX idx_rcv_files_group_member_id (group_member_id=?)
|
||||
SEARCH snd_files USING COVERING INDEX idx_snd_files_group_member_id (group_member_id=?)
|
||||
SEARCH group_member_intros USING COVERING INDEX idx_group_member_intros_to_group_member_id (to_group_member_id=?)
|
||||
|
@ -5044,7 +5088,7 @@ SEARCH chat_tags_chats USING COVERING INDEX idx_chat_tags_chats_chat_tag_id_grou
|
|||
SEARCH chat_item_moderations USING COVERING INDEX idx_chat_item_moderations_group_id (group_id=?)
|
||||
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_group_id (group_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_fwd_from_group_id (fwd_from_group_id=?)
|
||||
SCAN chat_items USING COVERING INDEX idx_chat_items_groups_user_mention
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_group_id (group_id=?)
|
||||
SEARCH messages USING COVERING INDEX idx_messages_group_id (group_id=?)
|
||||
SEARCH user_contact_links USING COVERING INDEX idx_user_contact_links_group_id (group_id=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_group_id (group_id=?)
|
||||
|
@ -5172,9 +5216,15 @@ SEARCH contact_profiles USING COVERING INDEX idx_contact_profiles_user_id (user_
|
|||
Query: DROP TABLE IF EXISTS temp_conn_ids
|
||||
Plan:
|
||||
|
||||
Query: DROP TABLE IF EXISTS temp_delete_members
|
||||
Plan:
|
||||
|
||||
Query: DROP TABLE temp_conn_ids
|
||||
Plan:
|
||||
|
||||
Query: DROP TABLE temp_delete_members
|
||||
Plan:
|
||||
|
||||
Query: INSERT INTO app_settings (app_settings) VALUES (?)
|
||||
Plan:
|
||||
|
||||
|
@ -5399,9 +5449,9 @@ Query: SELECT contact_id FROM contacts WHERE user_id = ? AND local_display_name
|
|||
Plan:
|
||||
SEARCH contacts USING INDEX sqlite_autoindex_contacts_1 (user_id=? AND local_display_name=?)
|
||||
|
||||
Query: SELECT contact_id FROM group_members WHERE user_id = ? AND contact_id = ? LIMIT 1
|
||||
Query: SELECT contact_id FROM group_members WHERE contact_id = ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_id (contact_id=?)
|
||||
|
||||
Query: SELECT contact_id, group_id FROM chat_items WHERE user_id = ? AND chat_item_id = ?
|
||||
Plan:
|
||||
|
@ -5451,10 +5501,6 @@ Query: SELECT group_id FROM user_contact_links WHERE user_id = ? AND user_contac
|
|||
Plan:
|
||||
SEARCH user_contact_links USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: SELECT group_member_id FROM group_members WHERE user_id = ? AND contact_profile_id = ? AND group_member_id != ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
|
||||
Query: SELECT group_member_id FROM group_members WHERE user_id = ? AND group_id = ? AND local_display_name = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_group_id (user_id=? AND group_id=?)
|
||||
|
@ -5549,7 +5595,7 @@ SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
|||
|
||||
Query: UPDATE connections SET conn_status='deleted' WHERE group_member_id = 3
|
||||
Plan:
|
||||
SCAN connections
|
||||
SEARCH connections USING INDEX idx_connections_group_member_id (group_member_id=?)
|
||||
|
||||
Query: UPDATE connections SET conn_type = ?, group_member_id = ?, updated_at = ? WHERE connection_id = ?
|
||||
Plan:
|
||||
|
|
|
@ -120,7 +120,6 @@ CREATE TABLE groups(
|
|||
updated_at TEXT CHECK(updated_at NOT NULL),
|
||||
chat_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL,
|
||||
enable_ntfs INTEGER,
|
||||
host_conn_custom_user_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL,
|
||||
unread_chat INTEGER DEFAULT 0 CHECK(unread_chat NOT NULL),
|
||||
chat_ts TEXT,
|
||||
favorite INTEGER NOT NULL DEFAULT 0,
|
||||
|
@ -658,7 +657,6 @@ CREATE INDEX idx_groups_inv_queue_info ON groups(inv_queue_info);
|
|||
CREATE INDEX idx_contact_requests_xcontact_id ON contact_requests(xcontact_id);
|
||||
CREATE INDEX idx_contacts_xcontact_id ON contacts(xcontact_id);
|
||||
CREATE INDEX idx_messages_shared_msg_id ON messages(shared_msg_id);
|
||||
CREATE INDEX idx_chat_items_shared_msg_id ON chat_items(shared_msg_id);
|
||||
CREATE UNIQUE INDEX idx_chat_items_direct_shared_msg_id ON chat_items(
|
||||
user_id,
|
||||
contact_id,
|
||||
|
@ -731,9 +729,6 @@ CREATE INDEX idx_group_members_contact_profile_id ON group_members(
|
|||
CREATE INDEX idx_group_members_user_id ON group_members(user_id);
|
||||
CREATE INDEX idx_group_members_invited_by ON group_members(invited_by);
|
||||
CREATE INDEX idx_group_profiles_user_id ON group_profiles(user_id);
|
||||
CREATE INDEX idx_groups_host_conn_custom_user_profile_id ON groups(
|
||||
host_conn_custom_user_profile_id
|
||||
);
|
||||
CREATE INDEX idx_groups_chat_item_id ON groups(chat_item_id);
|
||||
CREATE INDEX idx_groups_group_profile_id ON groups(group_profile_id);
|
||||
CREATE INDEX idx_messages_group_id ON messages(group_id);
|
||||
|
@ -1017,3 +1012,9 @@ CREATE INDEX idx_chat_items_groups_user_mention ON chat_items(
|
|||
item_status,
|
||||
user_mention
|
||||
);
|
||||
CREATE INDEX idx_chat_items_group_id ON chat_items(group_id);
|
||||
CREATE INDEX idx_connections_group_member_id ON connections(group_member_id);
|
||||
CREATE INDEX idx_chat_items_group_id_shared_msg_id ON chat_items(
|
||||
group_id,
|
||||
shared_msg_id
|
||||
);
|
||||
|
|
|
@ -577,18 +577,18 @@ safeDeleteLDN db User {userId} localDisplayName = do
|
|||
|
||||
type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe MemberId)
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Text, Maybe Text, Maybe ImageData, Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. BusinessChatInfoRow :. (Maybe UIThemeEntityOverrides, Maybe CustomData, Maybe Int64) :. GroupMemberRow
|
||||
|
||||
type GroupMemberRow = ((Int64, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences))
|
||||
|
||||
toGroupInfo :: VersionRangeChat -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, BI favorite, groupPreferences) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData, chatItemTTL) :. userMemberRow) =
|
||||
toGroupInfo vr userContactId chatTags ((groupId, localDisplayName, displayName, fullName, localAlias, description, image, enableNtfs_, sendRcpts, BI favorite, groupPreferences) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. businessRow :. (uiThemes, customData, chatItemTTL) :. userMemberRow) =
|
||||
let membership = (toGroupMember userContactId userMemberRow) {memberChatVRange = vr}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
groupProfile = GroupProfile {displayName, fullName, description, image, groupPreferences}
|
||||
businessChat = toBusinessChatInfo businessRow
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, chatTags, chatItemTTL, uiThemes, customData}
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, chatTags, chatItemTTL, uiThemes, customData}
|
||||
|
||||
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
|
||||
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, BI showMessages, memberRestriction_) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) =
|
||||
|
@ -610,7 +610,7 @@ groupInfoQuery =
|
|||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, g.local_alias, gp.description, gp.image,
|
||||
g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at, g.business_chat, g.business_member_id, g.customer_member_id, g.ui_themes, g.custom_data, g.chat_item_ttl,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
|
||||
|
|
|
@ -408,7 +408,6 @@ data GroupInfo = GroupInfo
|
|||
businessChat :: Maybe BusinessChatInfo,
|
||||
fullGroupPreferences :: FullGroupPreferences,
|
||||
membership :: GroupMember,
|
||||
hostConnCustomUserProfileId :: Maybe ProfileId,
|
||||
chatSettings :: ChatSettings,
|
||||
createdAt :: UTCTime,
|
||||
updatedAt :: UTCTime,
|
||||
|
|
|
@ -41,19 +41,6 @@ testAgentDB = "tests/tmp/test_agent.db"
|
|||
appSchema :: FilePath
|
||||
appSchema = "src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql"
|
||||
|
||||
-- Some indexes found by `.lint fkey-indexes` are not added to schema, explanation:
|
||||
--
|
||||
-- - CREATE INDEX 'chat_items_group_id' ON 'chat_items'('group_id'); --> groups(group_id)
|
||||
--
|
||||
-- Covering index is used instead. See for example:
|
||||
-- EXPLAIN QUERY PLAN DELETE FROM groups;
|
||||
-- (uses idx_chat_items_groups_item_status)
|
||||
--
|
||||
-- - CREATE INDEX 'connections_group_member_id' ON 'connections'('group_member_id'); --> group_members(group_member_id)
|
||||
--
|
||||
-- Covering index is used instead. See for example:
|
||||
-- EXPLAIN QUERY PLAN DELETE FROM group_members;
|
||||
-- (uses idx_connections_group_member)
|
||||
appLint :: FilePath
|
||||
appLint = "src/Simplex/Chat/Store/SQLite/Migrations/chat_lint.sql"
|
||||
|
||||
|
@ -136,7 +123,9 @@ skipComparisonForDownMigrations =
|
|||
-- sequence table moves down to the end of the file
|
||||
"20241023_chat_item_autoincrement_id",
|
||||
-- indexes move down to the end of the file
|
||||
"20241125_indexes"
|
||||
"20241125_indexes",
|
||||
-- indexes move down to the end of the file
|
||||
"20250130_indexes"
|
||||
]
|
||||
|
||||
getSchema :: FilePath -> FilePath -> IO String
|
||||
|
@ -158,7 +147,10 @@ saveQueryPlans = it "verify and overwrite query plans" $ \TestParams {chatQueryS
|
|||
appChatQueryPlans
|
||||
chatQueryStats
|
||||
(createChatStore (DBOpts testDB "" False True TQOff) MCError)
|
||||
(`DB.execute_` "CREATE TABLE IF NOT EXISTS temp_conn_ids (conn_id BLOB)")
|
||||
(\db -> do
|
||||
DB.execute_ db "CREATE TABLE IF NOT EXISTS temp_conn_ids (conn_id BLOB)"
|
||||
DB.execute_ db "CREATE TABLE IF NOT EXISTS temp_delete_members (contact_profile_id INTEGER, member_profile_id INTEGER, local_display_name TEXT)"
|
||||
)
|
||||
(agentSavedPlans, agentSavedPlans') <-
|
||||
updatePlans
|
||||
appAgentQueryPlans
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue