mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-28 05:24:44 +00:00
core: delete unused group contacts, don't create new ones (#5590)
* core: delete unused group contacts, don't create new ones * remove from exceptions * plans * fix tests * remove fixtures * update plans * update migration --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
co-authored by
Evgeny Poberezkin
parent
7f09de18d9
commit
5d18a49726
@@ -765,7 +765,6 @@ data ChatResponse
|
||||
| CRGroupLinkCreated {user :: User, groupInfo :: GroupInfo, connReqContact :: ConnReqContact, memberRole :: GroupMemberRole}
|
||||
| CRGroupLink {user :: User, groupInfo :: GroupInfo, connReqContact :: ConnReqContact, memberRole :: GroupMemberRole}
|
||||
| CRGroupLinkDeleted {user :: User, groupInfo :: GroupInfo}
|
||||
| CRAcceptingGroupJoinRequest {user :: User, groupInfo :: GroupInfo, contact :: Contact}
|
||||
| CRAcceptingGroupJoinRequestMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember}
|
||||
| CRNoMemberContactCreating {user :: User, groupInfo :: GroupInfo, member :: GroupMember} -- only used in CLI
|
||||
| CRNewMemberContact {user :: User, contact :: Contact, groupInfo :: GroupInfo, member :: GroupMember}
|
||||
|
||||
@@ -1095,26 +1095,7 @@ processChatCommand' vr = \case
|
||||
withStore' $ \db -> deleteGroupConnectionsAndFiles db user gInfo members
|
||||
withStore' $ \db -> deleteGroupItemsAndMembers db user gInfo members
|
||||
withStore' $ \db -> deleteGroup db user gInfo
|
||||
let contactIds = mapMaybe memberContactId members
|
||||
(errs1, (errs2, connIds)) <- lift $ second unzip . partitionEithers <$> withStoreBatch (\db -> map (deleteUnusedContact db) contactIds)
|
||||
let errs = errs1 <> mapMaybe (fmap ChatErrorStore) errs2
|
||||
unless (null errs) $ toView $ CRChatErrors (Just user) errs
|
||||
deleteAgentConnectionsAsync user $ concat connIds
|
||||
pure $ CRGroupDeletedUser user gInfo
|
||||
where
|
||||
deleteUnusedContact :: DB.Connection -> ContactId -> IO (Either ChatError (Maybe StoreError, [ConnId]))
|
||||
deleteUnusedContact db contactId = runExceptT . withExceptT ChatErrorStore $ do
|
||||
ct <- getContact db vr user contactId
|
||||
ifM
|
||||
((directOrUsed ct ||) . isJust <$> liftIO (checkContactHasGroups db user ct))
|
||||
(pure (Nothing, []))
|
||||
(getConnections ct)
|
||||
where
|
||||
getConnections :: Contact -> ExceptT StoreError IO (Maybe StoreError, [ConnId])
|
||||
getConnections ct = do
|
||||
conns <- liftIO $ getContactConnections db vr userId ct
|
||||
e_ <- (setContactDeleted db user ct $> Nothing) `catchStoreError` (pure . Just)
|
||||
pure (e_, map aConnId conns)
|
||||
CTLocal -> pure $ chatCmdError (Just user) "not supported"
|
||||
CTContactRequest -> pure $ chatCmdError (Just user) "not supported"
|
||||
APIClearChat (ChatRef cType chatId) -> withUser $ \user@User {userId} -> case cType of
|
||||
@@ -2986,10 +2967,9 @@ processChatCommand' vr = \case
|
||||
sendContactContentMessages :: User -> ContactId -> Bool -> Maybe Int -> NonEmpty ComposedMessageReq -> CM ChatResponse
|
||||
sendContactContentMessages user contactId live itemTTL cmrs = do
|
||||
assertMultiSendable live cmrs
|
||||
ct@Contact {contactUsed} <- withFastStore $ \db -> getContact db vr user contactId
|
||||
ct <- withFastStore $ \db -> getContact db vr user contactId
|
||||
assertDirectAllowed user MDSnd ct XMsgNew_
|
||||
assertVoiceAllowed ct
|
||||
unless contactUsed $ withFastStore' $ \db -> updateContactUsed db user ct
|
||||
processComposedMessages ct
|
||||
where
|
||||
assertVoiceAllowed :: Contact -> CM ()
|
||||
|
||||
@@ -797,15 +797,15 @@ acceptContactRequest user@User {userId} UserContactRequest {agentInvitationId =
|
||||
dm <- encodeConnInfoPQ pqSup' chatV $ XInfo profileToSend
|
||||
(ct,conn,) <$> withAgent (\a -> acceptContact a (aConnId conn) True invId dm pqSup' subMode)
|
||||
|
||||
acceptContactRequestAsync :: User -> UserContactRequest -> Maybe IncognitoProfile -> Bool -> PQSupport -> CM Contact
|
||||
acceptContactRequestAsync user cReq@UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = p, userContactLinkId, xContactId} incognitoProfile contactUsed pqSup = do
|
||||
acceptContactRequestAsync :: User -> UserContactRequest -> Maybe IncognitoProfile -> PQSupport -> CM Contact
|
||||
acceptContactRequestAsync user cReq@UserContactRequest {agentInvitationId = AgentInvId invId, cReqChatVRange, localDisplayName = cName, profileId, profile = p, userContactLinkId, xContactId} incognitoProfile pqSup = do
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
let profileToSend = profileToSendOnAccept user incognitoProfile False
|
||||
vr <- chatVersionRange
|
||||
let chatV = vr `peerConnChatVersion` cReqChatVRange
|
||||
(cmdId, acId) <- agentAcceptContactAsync user True invId (XInfo profileToSend) subMode pqSup chatV
|
||||
withStore' $ \db -> do
|
||||
(ct, Connection {connId}) <- createAcceptedContact db user acId chatV cReqChatVRange cName profileId p userContactLinkId xContactId incognitoProfile subMode pqSup contactUsed
|
||||
(ct, Connection {connId}) <- createAcceptedContact db user acId chatV cReqChatVRange cName profileId p userContactLinkId xContactId incognitoProfile subMode pqSup True
|
||||
deleteContactRequestRec db user cReq
|
||||
setCommandConnId db user cmdId connId
|
||||
pure ct
|
||||
|
||||
@@ -584,7 +584,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
lift $ setContactNetworkStatus ct' NSConnected
|
||||
toView $ CRContactConnected user ct' (fmap fromLocalProfile incognitoProfile)
|
||||
when (directOrUsed ct') $ do
|
||||
unless (contactUsed ct') $ withFastStore' $ \db -> updateContactUsed db user ct'
|
||||
createInternalChatItem user (CDDirectRcv ct') (CIRcvDirectE2EEInfo $ E2EInfo pqEnc) Nothing
|
||||
createFeatureEnabledItems ct'
|
||||
when (contactConnInitiated conn') $ do
|
||||
@@ -697,7 +696,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
-- [async agent commands] XGrpMemIntro continuation on receiving INV
|
||||
CFCreateConnGrpMemInv
|
||||
| maxVersion (peerChatVRange conn) >= groupDirectInvVersion -> sendWithoutDirectCReq
|
||||
| otherwise -> sendWithDirectCReq
|
||||
| otherwise -> messageError "processGroupMessage INV: member chat version range incompatible"
|
||||
where
|
||||
sendWithoutDirectCReq = do
|
||||
let GroupMember {groupMemberId, memberId} = m
|
||||
@@ -705,13 +704,6 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
liftIO $ setConnConnReqInv db user connId cReq
|
||||
getHostConnId db user groupId
|
||||
sendXGrpMemInv hostConnId Nothing XGrpMemIntroCont {groupId, groupMemberId, memberId, groupConnReq}
|
||||
sendWithDirectCReq = do
|
||||
let GroupMember {groupMemberId, memberId} = m
|
||||
contData <- withStore' $ \db -> do
|
||||
setConnConnReqInv db user connId cReq
|
||||
getXGrpMemIntroContGroup db user m
|
||||
forM_ contData $ \(hostConnId, directConnReq) ->
|
||||
sendXGrpMemInv hostConnId (Just directConnReq) XGrpMemIntroCont {groupId, groupMemberId, memberId, groupConnReq}
|
||||
-- [async agent commands] group link auto-accept continuation on receiving INV
|
||||
CFCreateConnGrpInv -> do
|
||||
ct <- withStore $ \db -> getContactViaMember db vr user m
|
||||
@@ -1310,9 +1302,9 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
case autoAccept of
|
||||
Just AutoAccept {acceptIncognito, businessAddress}
|
||||
| businessAddress ->
|
||||
if v < groupFastLinkJoinVersion || (isSimplexTeam && v < businessChatsVersion)
|
||||
if isSimplexTeam && v < businessChatsVersion
|
||||
then do
|
||||
ct <- acceptContactRequestAsync user cReq Nothing True reqPQSup
|
||||
ct <- acceptContactRequestAsync user cReq Nothing reqPQSup
|
||||
toView $ CRAcceptingContactRequest user ct
|
||||
else do
|
||||
gInfo <- acceptBusinessJoinRequestAsync user cReq
|
||||
@@ -1321,7 +1313,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
Nothing -> do
|
||||
-- [incognito] generate profile to send, create connection with incognito profile
|
||||
incognitoProfile <- if acceptIncognito then Just . NewIncognito <$> liftIO generateRandomProfile else pure Nothing
|
||||
ct <- acceptContactRequestAsync user cReq incognitoProfile True reqPQSup
|
||||
ct <- acceptContactRequestAsync user cReq incognitoProfile reqPQSup
|
||||
toView $ CRAcceptingContactRequest user ct
|
||||
Just groupId -> do
|
||||
gInfo <- withStore $ \db -> getGroupInfo db vr user groupId
|
||||
@@ -1331,10 +1323,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
mem <- acceptGroupJoinRequestAsync user gInfo cReq gLinkMemRole profileMode
|
||||
createInternalChatItem user (CDGroupRcv gInfo mem) (CIRcvGroupEvent RGEInvitedViaGroupLink) Nothing
|
||||
toView $ CRAcceptingGroupJoinRequestMember user gInfo mem
|
||||
else do
|
||||
-- TODO v5.7 remove old API (or v6.0?)
|
||||
ct <- acceptContactRequestAsync user cReq profileMode False PQSupportOff
|
||||
toView $ CRAcceptingGroupJoinRequest user gInfo ct
|
||||
else messageError "processUserContactRequest: chat version range incompatible for accepting group join request"
|
||||
_ -> toView $ CRReceivedContactRequest user cReq
|
||||
|
||||
memberCanSend :: GroupMember -> CM () -> CM ()
|
||||
@@ -1540,8 +1529,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
messageError = toView . CRMessageError user "error"
|
||||
|
||||
newContentMessage :: Contact -> MsgContainer -> RcvMessage -> MsgMeta -> CM ()
|
||||
newContentMessage ct@Contact {contactUsed} mc msg@RcvMessage {sharedMsgId_} msgMeta = do
|
||||
unless contactUsed $ withStore' $ \db -> updateContactUsed db user ct
|
||||
newContentMessage ct mc msg@RcvMessage {sharedMsgId_} msgMeta = do
|
||||
let ExtMsgContent content _ fInv_ _ _ = mcExtMsgContent mc
|
||||
-- Uncomment to test stuck delivery on errors - see test testDirectMessageDelete
|
||||
-- case content of
|
||||
@@ -1747,7 +1735,8 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
ExtMsgContent content mentions fInv_ itemTTL live_ = mcExtMsgContent mc
|
||||
ts@(_, ft_) = msgContentTexts content
|
||||
createBlockedByAdmin
|
||||
| groupFeatureAllowed SGFFullDelete gInfo = do -- ignores member role when blocked by admin
|
||||
| groupFeatureAllowed SGFFullDelete gInfo = do
|
||||
-- ignores member role when blocked by admin
|
||||
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs (ciContentNoParse CIRcvBlocked) Nothing timed' False M.empty
|
||||
ci' <- withStore' $ \db -> updateGroupCIBlockedByAdmin db user gInfo ci brokerTs
|
||||
groupMsgToView gInfo ci'
|
||||
@@ -2466,8 +2455,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
conn' <- updatePeerChatVRange activeConn chatVRange
|
||||
case chatMsgEvent of
|
||||
XInfo p -> do
|
||||
let contactUsed = connDirect activeConn
|
||||
ct <- withStore $ \db -> createDirectContact db user conn' p contactUsed
|
||||
ct <- withStore $ \db -> createDirectContact db user conn' p
|
||||
toView $ CRContactConnecting user ct
|
||||
pure (conn', False)
|
||||
XGrpLinkInv glInv -> do
|
||||
@@ -2505,17 +2493,16 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage =
|
||||
Right _ -> messageError "x.grp.mem.intro ignored: member already exists"
|
||||
Left _ -> do
|
||||
when (memberRole < GRAdmin) $ throwChatError (CEGroupContactRole c)
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
-- [async agent commands] commands should be asynchronous, continuation is to send XGrpMemInv - have to remember one has completed and process on second
|
||||
groupConnIds <- createConn subMode
|
||||
directConnIds <- case memChatVRange of
|
||||
Nothing -> Just <$> createConn subMode
|
||||
case memChatVRange of
|
||||
Nothing -> messageError "x.grp.mem.intro: member chat version range incompatible"
|
||||
Just (ChatVersionRange mcvr)
|
||||
| maxVersion mcvr >= groupDirectInvVersion -> pure Nothing
|
||||
| otherwise -> Just <$> createConn subMode
|
||||
let customUserProfileId = localProfileId <$> incognitoMembershipProfile gInfo
|
||||
chatV = maybe (minVersion vr) (\peerVR -> vr `peerConnChatVersion` fromChatVRange peerVR) memChatVRange
|
||||
void $ withStore $ \db -> createIntroReMember db user gInfo m chatV memInfo memRestrictions groupConnIds directConnIds customUserProfileId subMode
|
||||
| maxVersion mcvr >= groupDirectInvVersion -> do
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
-- [async agent commands] commands should be asynchronous, continuation is to send XGrpMemInv - have to remember one has completed and process on second
|
||||
groupConnIds <- createConn subMode
|
||||
let chatV = maybe (minVersion vr) (\peerVR -> vr `peerConnChatVersion` fromChatVRange peerVR) memChatVRange
|
||||
void $ withStore $ \db -> createIntroReMember db user gInfo m chatV memInfo memRestrictions groupConnIds subMode
|
||||
| otherwise -> messageError "x.grp.mem.intro: member chat version range incompatible"
|
||||
_ -> messageError "x.grp.mem.intro can be only sent by host member"
|
||||
where
|
||||
createConn subMode = createAgentConnectionAsync user CFCreateConnGrpMemInv (chatHasNtfs chatSettings) SCMInvitation subMode
|
||||
|
||||
@@ -46,7 +46,6 @@ module Simplex.Chat.Store.Direct
|
||||
updateContactConnectionAlias,
|
||||
updatePCCIncognito,
|
||||
deletePCCIncognitoProfile,
|
||||
updateContactUsed,
|
||||
updateContactUnreadChat,
|
||||
setUserChatsRead,
|
||||
updateContactStatus,
|
||||
@@ -240,10 +239,10 @@ createIncognitoProfile db User {userId} p = do
|
||||
createdAt <- getCurrentTime
|
||||
createIncognitoProfile_ db userId createdAt p
|
||||
|
||||
createDirectContact :: DB.Connection -> User -> Connection -> Profile -> Bool -> ExceptT StoreError IO Contact
|
||||
createDirectContact db user@User {userId} conn@Connection {connId, localAlias} p@Profile {preferences} contactUsed = do
|
||||
createDirectContact :: DB.Connection -> User -> Connection -> Profile -> ExceptT StoreError IO Contact
|
||||
createDirectContact db user@User {userId} conn@Connection {connId, localAlias} p@Profile {preferences} = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
(localDisplayName, contactId, profileId) <- createContact_ db userId p localAlias Nothing currentTs contactUsed
|
||||
(localDisplayName, contactId, profileId) <- createContact_ db userId p localAlias Nothing currentTs
|
||||
liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, connId)
|
||||
let profile = toLocalProfile profileId p localAlias
|
||||
userPreferences = emptyChatPrefs
|
||||
@@ -255,7 +254,7 @@ createDirectContact db user@User {userId} conn@Connection {connId, localAlias} p
|
||||
profile,
|
||||
activeConn = Just conn,
|
||||
viaGroup = Nothing,
|
||||
contactUsed,
|
||||
contactUsed = True,
|
||||
contactStatus = CSActive,
|
||||
chatSettings = defaultChatSettings,
|
||||
userPreferences,
|
||||
@@ -471,11 +470,6 @@ deletePCCIncognitoProfile db User {userId} profileId =
|
||||
|]
|
||||
(userId, profileId)
|
||||
|
||||
updateContactUsed :: DB.Connection -> User -> Contact -> IO ()
|
||||
updateContactUsed db User {userId} Contact {contactId} = do
|
||||
updatedAt <- getCurrentTime
|
||||
DB.execute db "UPDATE contacts SET contact_used = 1, updated_at = ? WHERE user_id = ? AND contact_id = ?" (updatedAt, userId, contactId)
|
||||
|
||||
updateContactUnreadChat :: DB.Connection -> User -> Contact -> Bool -> IO ()
|
||||
updateContactUnreadChat db User {userId} Contact {contactId} unreadChat = do
|
||||
updatedAt <- getCurrentTime
|
||||
|
||||
@@ -110,7 +110,6 @@ module Simplex.Chat.Store.Groups
|
||||
updateGroupMemberSettings,
|
||||
updateGroupMemberBlocked,
|
||||
getXGrpMemIntroContDirect,
|
||||
getXGrpMemIntroContGroup,
|
||||
getHostConnId,
|
||||
createMemberContact,
|
||||
getMemberContact,
|
||||
@@ -1397,33 +1396,23 @@ getForwardInvitedMembers db vr user forwardMember highlyAvailable = do
|
||||
WHERE re_group_member_id = ? AND intro_status NOT IN (?,?,?)
|
||||
|]
|
||||
|
||||
createIntroReMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> VersionChat -> MemberInfo -> Maybe MemberRestrictions -> (CommandId, ConnId) -> Maybe (CommandId, ConnId) -> Maybe ProfileId -> SubscriptionMode -> ExceptT StoreError IO GroupMember
|
||||
createIntroReMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> VersionChat -> MemberInfo -> Maybe MemberRestrictions -> (CommandId, ConnId) -> SubscriptionMode -> ExceptT StoreError IO GroupMember
|
||||
createIntroReMember
|
||||
db
|
||||
user@User {userId}
|
||||
gInfo@GroupInfo {groupId}
|
||||
gInfo
|
||||
_host@GroupMember {memberContactId, activeConn}
|
||||
chatV
|
||||
memInfo@(MemberInfo _ _ memChatVRange memberProfile)
|
||||
memRestrictions_
|
||||
(groupCmdId, groupAgentConnId)
|
||||
directConnIds
|
||||
customUserProfileId
|
||||
subMode = do
|
||||
let mcvr = maybe chatInitialVRange fromChatVRange memChatVRange
|
||||
cLevel = 1 + maybe 0 (\Connection {connLevel} -> connLevel) activeConn
|
||||
memRestriction = restriction <$> memRestrictions_
|
||||
currentTs <- liftIO getCurrentTime
|
||||
newMember <- case directConnIds of
|
||||
Just (directCmdId, directAgentConnId) -> do
|
||||
Connection {connId = directConnId} <- liftIO $ createConnection_ db userId ConnContact Nothing directAgentConnId ConnNew chatV mcvr memberContactId Nothing customUserProfileId cLevel currentTs subMode PQSupportOff
|
||||
liftIO $ setCommandConnId db user directCmdId directConnId
|
||||
(localDisplayName, contactId, memProfileId) <- createContact_ db userId memberProfile "" (Just groupId) currentTs False
|
||||
liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, directConnId)
|
||||
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Just contactId, memProfileId}
|
||||
Nothing -> do
|
||||
(localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs
|
||||
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId}
|
||||
(localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs
|
||||
let newMember = NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memRestriction, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId}
|
||||
liftIO $ do
|
||||
member <- createNewMember_ db user gInfo newMember currentTs
|
||||
conn@Connection {connId = groupConnId} <- createMemberConnection_ db userId (groupMemberId' member) groupAgentConnId chatV mcvr memberContactId cLevel currentTs subMode
|
||||
@@ -1850,12 +1839,6 @@ mergeContactRecords db vr user@User {userId} to@Contact {localDisplayName = keep
|
||||
assertNotUser db user fromCt
|
||||
liftIO $ do
|
||||
currentTs <- getCurrentTime
|
||||
-- next query fixes incorrect unused contacts deletion
|
||||
when (contactDirect toCt && not (contactUsed toCt)) $
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE contacts SET contact_used = 1, updated_at = ? WHERE user_id = ? AND contact_id = ?"
|
||||
(currentTs, userId, toContactId)
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE connections SET contact_id = ?, updated_at = ? WHERE contact_id = ? AND user_id = ?"
|
||||
@@ -2061,36 +2044,6 @@ getXGrpMemIntroContDirect db User {userId} Contact {contactId} = do
|
||||
Just groupConnReq -> Just (hostConnId, XGrpMemIntroCont {groupId, groupMemberId, memberId, groupConnReq})
|
||||
_ -> Nothing
|
||||
|
||||
getXGrpMemIntroContGroup :: DB.Connection -> User -> GroupMember -> IO (Maybe (Int64, ConnReqInvitation))
|
||||
getXGrpMemIntroContGroup db User {userId} GroupMember {groupMemberId} = do
|
||||
fmap join . maybeFirstRow toCont $
|
||||
DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT ch.connection_id, c.conn_req_inv
|
||||
FROM group_members m
|
||||
JOIN contacts ct ON ct.contact_id = m.contact_id
|
||||
LEFT JOIN connections c ON c.connection_id = (
|
||||
SELECT MAX(cc.connection_id)
|
||||
FROM connections cc
|
||||
WHERE cc.contact_id = ct.contact_id
|
||||
)
|
||||
JOIN groups g ON g.group_id = m.group_id AND g.group_id = ct.via_group
|
||||
JOIN group_members mh ON mh.group_id = g.group_id
|
||||
LEFT JOIN connections ch ON ch.connection_id = (
|
||||
SELECT max(cc.connection_id)
|
||||
FROM connections cc
|
||||
where cc.user_id = ? AND cc.group_member_id = mh.group_member_id
|
||||
)
|
||||
WHERE m.user_id = ? AND m.group_member_id = ? AND mh.member_category = ? AND ct.deleted = 0
|
||||
|]
|
||||
(userId, userId, groupMemberId, GCHostMember)
|
||||
where
|
||||
toCont :: (Int64, Maybe ConnReqInvitation) -> Maybe (Int64, ConnReqInvitation)
|
||||
toCont (hostConnId, connReq_) = case connReq_ of
|
||||
Just connReq -> Just (hostConnId, connReq)
|
||||
_ -> Nothing
|
||||
|
||||
getHostConnId :: DB.Connection -> User -> GroupId -> ExceptT StoreError IO GroupMemberId
|
||||
getHostConnId db user@User {userId} groupId = do
|
||||
hostMemberId <- getHostMemberId_ db user groupId
|
||||
|
||||
@@ -2562,8 +2562,7 @@ getGroupChatItemIdByText db User {userId, localDisplayName = userName} groupId c
|
||||
SELECT i.chat_item_id
|
||||
FROM chat_items i
|
||||
JOIN group_members m ON m.group_member_id = i.group_member_id
|
||||
JOIN contacts c ON c.contact_id = m.contact_id
|
||||
WHERE i.user_id = ? AND i.group_id = ? AND c.local_display_name = ? AND i.item_text like ?
|
||||
WHERE i.user_id = ? AND i.group_id = ? AND m.local_display_name = ? AND i.item_text like ?
|
||||
ORDER BY i.chat_item_id DESC
|
||||
LIMIT 1
|
||||
|]
|
||||
|
||||
@@ -126,6 +126,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20250105_indexes
|
||||
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.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||
@@ -251,7 +252,8 @@ schemaMigrations =
|
||||
("20250105_indexes", m20250105_indexes, Just down_m20250105_indexes),
|
||||
("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)
|
||||
("20250126_mentions", m20250126_mentions, Just down_m20250126_mentions),
|
||||
("20250129_delete_unused_contacts", m20250129_delete_unused_contacts, Just down_m20250129_delete_unused_contacts)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.SQLite.Migrations.M20250129_delete_unused_contacts where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20250129_delete_unused_contacts :: Query
|
||||
m20250129_delete_unused_contacts =
|
||||
[sql|
|
||||
CREATE TEMPORARY TABLE temp_delete_contacts (
|
||||
contact_id INTEGER PRIMARY KEY,
|
||||
contact_profile_id INTEGER NOT NULL,
|
||||
local_display_name TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO temp_delete_contacts(contact_id, contact_profile_id, local_display_name)
|
||||
SELECT contact_id, contact_profile_id, local_display_name
|
||||
FROM contacts
|
||||
WHERE contact_used = 0 AND is_user = 0
|
||||
AND contact_id NOT IN (SELECT contact_id FROM users)
|
||||
AND contact_id NOT IN (SELECT contact_id FROM contact_requests);
|
||||
|
||||
CREATE TEMPORARY TABLE temp_delete_profiles (contact_profile_id INTEGER PRIMARY KEY);
|
||||
|
||||
INSERT OR IGNORE INTO temp_delete_profiles(contact_profile_id)
|
||||
SELECT custom_user_profile_id FROM connections
|
||||
WHERE contact_id IN (SELECT contact_id FROM temp_delete_contacts)
|
||||
AND custom_user_profile_id IS NOT NULL;
|
||||
|
||||
UPDATE group_members SET contact_id = NULL
|
||||
WHERE contact_id IN (SELECT contact_id FROM temp_delete_contacts);
|
||||
|
||||
DELETE FROM connections
|
||||
WHERE contact_id IN (SELECT contact_id FROM temp_delete_contacts);
|
||||
|
||||
DELETE FROM contacts
|
||||
WHERE contact_id IN (SELECT contact_id FROM temp_delete_contacts);
|
||||
|
||||
DELETE FROM contact_profiles
|
||||
WHERE
|
||||
(contact_profile_id IN (SELECT contact_profile_id FROM temp_delete_profiles)
|
||||
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 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 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);
|
||||
|
||||
DROP TABLE temp_delete_contacts;
|
||||
DROP TABLE temp_delete_profiles;
|
||||
|]
|
||||
|
||||
down_m20250129_delete_unused_contacts :: Query
|
||||
down_m20250129_delete_unused_contacts =
|
||||
[sql|
|
||||
|]
|
||||
@@ -646,30 +646,6 @@ Query:
|
||||
|
||||
Plan:
|
||||
|
||||
Query:
|
||||
INSERT INTO contacts (contact_profile_id, via_group, local_display_name, user_id, created_at, updated_at, chat_ts)
|
||||
SELECT contact_profile_id, group_id, ?, ?, ?, ?, ?
|
||||
FROM group_members
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH chat_tags_chats USING COVERING INDEX idx_chat_tags_chats_chat_tag_id_contact_id (contact_id=?)
|
||||
SEARCH received_probes USING COVERING INDEX idx_received_probes_contact_id (contact_id=?)
|
||||
SEARCH sent_probe_hashes USING COVERING INDEX idx_sent_probe_hashes_contact_id (contact_id=?)
|
||||
SEARCH sent_probes USING COVERING INDEX idx_sent_probes_contact_id (contact_id=?)
|
||||
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_contact_id (contact_id=?)
|
||||
SEARCH calls USING COVERING INDEX idx_calls_contact_id (contact_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_fwd_from_contact_id (fwd_from_contact_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_contact_id (contact_id=?)
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_id (contact_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_contact_id (contact_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_via_contact (via_contact=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_contact_id (contact_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_id (contact_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_invited_by (invited_by=?)
|
||||
SEARCH users USING COVERING INDEX sqlite_autoindex_users_1 (contact_id=?)
|
||||
|
||||
Query:
|
||||
INSERT INTO group_members
|
||||
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
|
||||
@@ -1145,15 +1121,13 @@ Query:
|
||||
SELECT i.chat_item_id
|
||||
FROM chat_items i
|
||||
JOIN group_members m ON m.group_member_id = i.group_member_id
|
||||
JOIN contacts c ON c.contact_id = m.contact_id
|
||||
WHERE i.user_id = ? AND i.group_id = ? AND c.local_display_name = ? AND i.item_text like ?
|
||||
WHERE i.user_id = ? AND i.group_id = ? AND m.local_display_name = ? AND i.item_text like ?
|
||||
ORDER BY i.chat_item_id DESC
|
||||
LIMIT 1
|
||||
|
||||
Plan:
|
||||
SEARCH i USING INDEX idx_chat_items_groups_user_mention (user_id=? AND group_id=?)
|
||||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INTEGER PRIMARY KEY (rowid=?)
|
||||
USE TEMP B-TREE FOR ORDER BY
|
||||
|
||||
Query:
|
||||
@@ -1227,14 +1201,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET contact_id = ?, updated_at = ?
|
||||
WHERE group_member_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET contact_id = ?, updated_at = ?
|
||||
@@ -2787,66 +2753,6 @@ Plan:
|
||||
SEARCH c USING INDEX idx_connections_updated_at (user_id=?)
|
||||
SEARCH uc USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT ch.connection_id, c.conn_req_inv
|
||||
FROM group_members m
|
||||
JOIN contacts ct ON ct.contact_id = m.contact_id
|
||||
LEFT JOIN connections c ON c.connection_id = (
|
||||
SELECT MAX(cc.connection_id)
|
||||
FROM connections cc
|
||||
WHERE cc.contact_id = ct.contact_id
|
||||
)
|
||||
JOIN groups g ON g.group_id = m.group_id AND g.group_id = ct.via_group
|
||||
JOIN group_members mh ON mh.group_id = g.group_id
|
||||
LEFT JOIN connections ch ON ch.connection_id = (
|
||||
SELECT max(cc.connection_id)
|
||||
FROM connections cc
|
||||
where cc.user_id = ? AND cc.group_member_id = mh.group_member_id
|
||||
)
|
||||
WHERE m.user_id = ? AND m.group_member_id = ? AND mh.member_category = ? AND ct.deleted = 0
|
||||
|
||||
Plan:
|
||||
SEARCH m USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH ct USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH c USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH cc USING COVERING INDEX idx_connections_contact_id (contact_id=?)
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH mh USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
|
||||
SEARCH ch USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 2
|
||||
SEARCH cc USING COVERING INDEX idx_connections_group_member (user_id=? AND group_member_id=?)
|
||||
|
||||
Query:
|
||||
SELECT ch.connection_id, g.group_id, m.group_member_id, m.member_id, c.conn_req_inv
|
||||
FROM contacts ct
|
||||
JOIN group_members m ON m.contact_id = ct.contact_id
|
||||
LEFT JOIN connections c ON c.connection_id = (
|
||||
SELECT MAX(cc.connection_id)
|
||||
FROM connections cc
|
||||
WHERE cc.group_member_id = m.group_member_id
|
||||
)
|
||||
JOIN groups g ON g.group_id = m.group_id AND g.group_id = ct.via_group
|
||||
JOIN group_members mh ON mh.group_id = g.group_id
|
||||
LEFT JOIN connections ch ON ch.connection_id = (
|
||||
SELECT max(cc.connection_id)
|
||||
FROM connections cc
|
||||
where cc.user_id = ? AND cc.group_member_id = mh.group_member_id
|
||||
)
|
||||
WHERE ct.user_id = ? AND ct.contact_id = ? AND ct.deleted = 0 AND mh.member_category = ?
|
||||
|
||||
Plan:
|
||||
SEARCH ct USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH m USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
|
||||
SEARCH c USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 1
|
||||
SEARCH cc
|
||||
SEARCH mh USING INDEX sqlite_autoindex_group_members_1 (group_id=?)
|
||||
SEARCH ch USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN
|
||||
CORRELATED SCALAR SUBQUERY 2
|
||||
SEARCH cc USING COVERING INDEX idx_connections_group_member (user_id=? AND group_member_id=?)
|
||||
|
||||
Query:
|
||||
SELECT chat_item_id
|
||||
FROM chat_item_messages
|
||||
@@ -3112,30 +3018,6 @@ Plan:
|
||||
SEARCH ct USING INDEX idx_contacts_chat_ts (user_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT ct.contact_id
|
||||
FROM contacts ct
|
||||
JOIN contact_profiles p ON ct.contact_profile_id = p.contact_profile_id
|
||||
WHERE ct.user_id = ? AND ct.contact_id != ?
|
||||
AND ct.contact_status = ? AND ct.deleted = 0 AND ct.is_user = 0
|
||||
AND p.display_name = ? AND p.full_name = ?
|
||||
AND p.image = ?
|
||||
Plan:
|
||||
SEARCH ct USING INDEX idx_contacts_chat_ts (user_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT ct.contact_id
|
||||
FROM contacts ct
|
||||
JOIN contact_profiles p ON ct.contact_profile_id = p.contact_profile_id
|
||||
WHERE ct.user_id = ? AND ct.contact_id != ?
|
||||
AND ct.contact_status = ? AND ct.deleted = 0 AND ct.is_user = 0
|
||||
AND p.display_name = ? AND p.full_name = ?
|
||||
AND p.image is NULL
|
||||
Plan:
|
||||
SEARCH ct USING INDEX idx_contacts_chat_ts (user_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT d.file_descr_id, d.file_descr_text, d.file_descr_part_no, d.file_descr_complete
|
||||
FROM xftp_file_descriptions d
|
||||
@@ -3269,18 +3151,6 @@ Plan:
|
||||
SEARCH m USING INDEX idx_group_members_user_id (user_id=?)
|
||||
SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT m.member_role, gp.preferences
|
||||
FROM groups g
|
||||
JOIN group_profiles gp USING (group_profile_id)
|
||||
JOIN group_members m USING (group_id)
|
||||
WHERE g.user_id = ? AND m.contact_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH m USING INDEX idx_group_members_contact_id (contact_id=?)
|
||||
SEARCH g USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH gp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT pgm.message_id, m.shared_msg_id, m.msg_body, m.chat_msg_event, pgm.group_member_intro_id
|
||||
FROM pending_group_messages pgm
|
||||
@@ -3482,22 +3352,6 @@ Query:
|
||||
Plan:
|
||||
SEARCH group_member_intros USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET contact_id = ?,
|
||||
local_display_name = (SELECT local_display_name FROM contacts WHERE contact_id = ?),
|
||||
contact_profile_id = (SELECT contact_profile_id FROM contacts WHERE contact_id = ?),
|
||||
updated_at = ?
|
||||
WHERE contact_id = ?
|
||||
AND user_id = ?
|
||||
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
SCALAR SUBQUERY 1
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SCALAR SUBQUERY 2
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE group_members
|
||||
SET contact_id = ?, local_display_name = ?, contact_profile_id = ?, updated_at = ?
|
||||
@@ -5092,25 +4946,6 @@ Query: DELETE FROM contact_requests WHERE user_id = ? AND contact_request_id = ?
|
||||
Plan:
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: DELETE FROM contacts WHERE contact_id = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH chat_tags_chats USING COVERING INDEX idx_chat_tags_chats_chat_tag_id_contact_id (contact_id=?)
|
||||
SEARCH received_probes USING COVERING INDEX idx_received_probes_contact_id (contact_id=?)
|
||||
SEARCH sent_probe_hashes USING COVERING INDEX idx_sent_probe_hashes_contact_id (contact_id=?)
|
||||
SEARCH sent_probes USING COVERING INDEX idx_sent_probes_contact_id (contact_id=?)
|
||||
SEARCH chat_item_reactions USING COVERING INDEX idx_chat_item_reactions_contact_id (contact_id=?)
|
||||
SEARCH calls USING COVERING INDEX idx_calls_contact_id (contact_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_fwd_from_contact_id (fwd_from_contact_id=?)
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_contact_id (contact_id=?)
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_id (contact_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_contact_id (contact_id=?)
|
||||
SEARCH connections USING COVERING INDEX idx_connections_via_contact (via_contact=?)
|
||||
SEARCH files USING COVERING INDEX idx_files_contact_id (contact_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_contact_id (contact_id=?)
|
||||
SEARCH group_members USING COVERING INDEX idx_group_members_invited_by (invited_by=?)
|
||||
SEARCH users USING COVERING INDEX sqlite_autoindex_users_1 (contact_id=?)
|
||||
|
||||
Query: DELETE FROM contacts WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -5596,10 +5431,6 @@ Query: SELECT group_id FROM group_members WHERE group_member_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: SELECT group_id FROM group_members WHERE user_id = ? AND contact_id = ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
|
||||
Query: SELECT group_id FROM groups WHERE inv_queue_info = ? AND user_id = ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH groups USING INDEX idx_groups_chat_ts (user_id=?)
|
||||
@@ -5620,10 +5451,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_link_id FROM user_contact_links WHERE user_id = ? AND group_id = ? LIMIT 1
|
||||
Plan:
|
||||
SEARCH user_contact_links USING INDEX idx_user_contact_links_group_id (group_id=?)
|
||||
|
||||
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=?)
|
||||
@@ -5684,10 +5511,6 @@ Query: SELECT xgrplinkmem_received FROM group_members WHERE group_member_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE chat_items SET contact_id = ?, updated_at = ? WHERE contact_id = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING COVERING INDEX idx_chat_items_contacts_created_at (user_id=? AND contact_id=?)
|
||||
|
||||
Query: UPDATE chat_items SET item_status = ?, updated_at = ? WHERE user_id = ? AND contact_id = ? AND chat_item_id = ?
|
||||
Plan:
|
||||
SEARCH chat_items USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -5740,10 +5563,6 @@ Query: UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id
|
||||
Plan:
|
||||
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE connections SET contact_id = ?, updated_at = ? WHERE contact_id = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH connections USING INDEX idx_connections_contact_id (contact_id=?)
|
||||
|
||||
Query: UPDATE connections SET quota_err_counter = ?, updated_at = ? WHERE user_id = ? AND connection_id = ?
|
||||
Plan:
|
||||
SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -5756,10 +5575,6 @@ Query: UPDATE connections SET to_subscribe = 0 WHERE to_subscribe = 1
|
||||
Plan:
|
||||
SEARCH connections USING INDEX idx_connections_to_subscribe (to_subscribe=?)
|
||||
|
||||
Query: UPDATE connections SET via_contact = ?, updated_at = ? WHERE via_contact = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH connections USING INDEX idx_connections_via_contact (via_contact=?)
|
||||
|
||||
Query: UPDATE contact_requests SET contact_id = ? WHERE user_id = ? AND local_display_name = ?
|
||||
Plan:
|
||||
SEARCH contact_requests USING INDEX sqlite_autoindex_contact_requests_1 (user_id=? AND local_display_name=?)
|
||||
@@ -5780,18 +5595,10 @@ Query: UPDATE contacts SET contact_grp_inv_sent = ?, updated_at = ? WHERE contac
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET contact_used = 1, updated_at = ? WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET contact_used = ? WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET deleted = 1, updated_at = ? WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contacts SET enable_ntfs = ?, send_rcpts = ?, favorite = ? WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -5864,10 +5671,6 @@ Query: UPDATE group_members SET contact_id = NULL, updated_at = ? WHERE user_id
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
|
||||
Query: UPDATE group_members SET invited_by = ?, updated_at = ? WHERE invited_by = ? AND user_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_invited_by (invited_by=?)
|
||||
|
||||
Query: UPDATE group_members SET local_display_name = ?, updated_at = ? WHERE user_id = ? AND contact_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INDEX idx_group_members_user_id (user_id=?)
|
||||
@@ -5884,10 +5687,6 @@ Query: UPDATE group_members SET member_role = ? WHERE user_id = ? AND group_memb
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE group_members SET sent_inv_queue_info = ?, updated_at = ? WHERE user_id = ? AND group_member_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE group_members SET xgrplinkmem_received = ?, updated_at = ? WHERE group_member_id = ?
|
||||
Plan:
|
||||
SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -5980,10 +5779,6 @@ Query: UPDATE usage_conditions SET notified_at = ? WHERE usage_conditions_id = ?
|
||||
Plan:
|
||||
SEARCH usage_conditions USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE user_contact_links SET group_link_member_role = ? WHERE user_id = ? AND user_contact_link_id = ?
|
||||
Plan:
|
||||
SEARCH user_contact_links USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE users SET active_user = 0
|
||||
Plan:
|
||||
SCAN users
|
||||
|
||||
@@ -381,10 +381,10 @@ setCommandConnId db User {userId} cmdId connId = do
|
||||
createContact :: DB.Connection -> User -> Profile -> ExceptT StoreError IO ()
|
||||
createContact db User {userId} profile = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
void $ createContact_ db userId profile "" Nothing currentTs True
|
||||
void $ createContact_ db userId profile "" Nothing currentTs
|
||||
|
||||
createContact_ :: DB.Connection -> UserId -> Profile -> LocalAlias -> Maybe Int64 -> UTCTime -> Bool -> ExceptT StoreError IO (Text, ContactId, ProfileId)
|
||||
createContact_ db userId Profile {displayName, fullName, image, contactLink, preferences} localAlias viaGroup currentTs contactUsed =
|
||||
createContact_ :: DB.Connection -> UserId -> Profile -> LocalAlias -> Maybe Int64 -> UTCTime -> ExceptT StoreError IO (Text, ContactId, ProfileId)
|
||||
createContact_ db userId Profile {displayName, fullName, image, contactLink, preferences} localAlias viaGroup currentTs =
|
||||
ExceptT . withLocalDisplayName db userId displayName $ \ldn -> do
|
||||
DB.execute
|
||||
db
|
||||
@@ -394,7 +394,7 @@ createContact_ db userId Profile {displayName, fullName, image, contactLink, pre
|
||||
DB.execute
|
||||
db
|
||||
"INSERT INTO contacts (contact_profile_id, local_display_name, user_id, via_group, created_at, updated_at, chat_ts, contact_used) VALUES (?,?,?,?,?,?,?,?)"
|
||||
(profileId, ldn, userId, viaGroup, currentTs, currentTs, currentTs, BI contactUsed)
|
||||
(profileId, ldn, userId, viaGroup, currentTs, currentTs, currentTs, BI True)
|
||||
contactId <- insertedRowId db
|
||||
pure $ Right (ldn, contactId, profileId)
|
||||
|
||||
|
||||
@@ -315,7 +315,6 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe
|
||||
CRGroupLinkCreated u g cReq mRole -> ttyUser u $ groupLink_ "Group link is created!" g cReq mRole
|
||||
CRGroupLink u g cReq mRole -> ttyUser u $ groupLink_ "Group link:" g cReq mRole
|
||||
CRGroupLinkDeleted u g -> ttyUser u $ viewGroupLinkDeleted g
|
||||
CRAcceptingGroupJoinRequest _ g c -> [ttyFullContact c <> ": accepting request to join group " <> ttyGroup' g <> "..."]
|
||||
CRAcceptingGroupJoinRequestMember _ g m -> [ttyFullMember m <> ": accepting request to join group " <> ttyGroup' g <> "..."]
|
||||
CRNoMemberContactCreating u g m -> ttyUser u ["member " <> ttyGroup' g <> " " <> ttyMember m <> " does not have direct connection, creating"]
|
||||
CRNewMemberContact u _ g m -> ttyUser u ["contact for member " <> ttyGroup' g <> " " <> ttyMember m <> " is created"]
|
||||
|
||||
Reference in New Issue
Block a user