Skip to content

Commit 2650050

Browse files
committed
Update SQL query statement
1 parent ea95bad commit 2650050

8 files changed

Lines changed: 168 additions & 56 deletions

File tree

Mixin/Service/DeviceTransfer/DeviceTransferServerDataSource.swift

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ final class DeviceTransferServerDataSource {
1010
private let remotePlatform: DeviceTransferPlatform
1111
private let fileContentBuffer: UnsafeMutablePointer<UInt8>
1212
private let filter: DeviceTransferFilter
13-
private let conversationIDs: [String]?
1413
private let fromDate: String?
14+
private let conversationIDs: [String]?
15+
private let conversationIDsForFetching: [String]?
1516

1617
private var transcriptMessageCount = 0
1718

@@ -20,8 +21,9 @@ final class DeviceTransferServerDataSource {
2021
self.remotePlatform = remotePlatform
2122
self.fileContentBuffer = .allocate(capacity: fileChunkSize)
2223
self.filter = filter
23-
conversationIDs = filter.conversation.ids
2424
fromDate = filter.time.utcString
25+
conversationIDs = filter.conversation.ids
26+
conversationIDsForFetching = filter.conversation.idsForFetching
2527
}
2628

2729
deinit {
@@ -186,11 +188,14 @@ extension DeviceTransferServerDataSource {
186188
case .conversation:
187189
let conversations = ConversationDAO.shared.conversations(limit: limit,
188190
after: location.primaryID,
189-
matching: conversationIDs)
191+
matching: conversationIDsForFetching)
190192
databaseItemCount = conversations.count
191193
nextPrimaryID = conversations.last?.conversationId
192194
nextSecondaryID = nil
193195
transferItems = conversations.compactMap { conversation in
196+
guard filter.isValidItem(conversationID: conversation.conversationId) else {
197+
return nil
198+
}
194199
let deviceTransferConversation = DeviceTransferConversation(conversation: conversation, to: remotePlatform)
195200
do {
196201
let outputData = try DeviceTransferProtocol.output(type: location.type, data: deviceTransferConversation, key: key)
@@ -204,11 +209,14 @@ extension DeviceTransferServerDataSource {
204209
let participants = ParticipantDAO.shared.participants(limit: limit,
205210
after: location.primaryID,
206211
with: location.secondaryID,
207-
matching: conversationIDs)
212+
matching: conversationIDsForFetching)
208213
databaseItemCount = participants.count
209214
nextPrimaryID = participants.last?.conversationId
210215
nextSecondaryID = participants.last?.userId
211216
transferItems = participants.compactMap { participant in
217+
guard filter.isValidItem(conversationID: participant.conversationId) else {
218+
return nil
219+
}
212220
let deviceTransferParticipant = DeviceTransferParticipant(participant: participant)
213221
do {
214222
let outputData = try DeviceTransferProtocol.output(type: location.type, data: deviceTransferParticipant, key: key)
@@ -308,7 +316,9 @@ extension DeviceTransferServerDataSource {
308316
rowID = -1
309317
}
310318
}
311-
let pinMessages = PinMessageDAO.shared.pinMessages(limit: limit, after: rowID, matching: conversationIDs)
319+
let pinMessages = PinMessageDAO.shared.pinMessages(limit: limit,
320+
after: rowID,
321+
matching: conversationIDsForFetching)
312322
databaseItemCount = pinMessages.count
313323
if let messageID = pinMessages.last?.messageId, let rowID = PinMessageDAO.shared.messageRowID(messageID: messageID) {
314324
nextPrimaryID = "\(rowID)"
@@ -317,6 +327,9 @@ extension DeviceTransferServerDataSource {
317327
}
318328
nextSecondaryID = nil
319329
transferItems = pinMessages.compactMap { pinMessage in
330+
guard filter.isValidItem(conversationID: pinMessage.conversationId) else {
331+
return nil
332+
}
320333
if let fromDate, pinMessage.createdAt < fromDate {
321334
return nil
322335
}
@@ -354,7 +367,9 @@ extension DeviceTransferServerDataSource {
354367
rowID = -1
355368
}
356369
}
357-
let messages = MessageDAO.shared.messages(limit: limit, after: rowID, matching: conversationIDs)
370+
let messages = MessageDAO.shared.messages(limit: limit,
371+
after: rowID,
372+
matching: conversationIDsForFetching)
358373
databaseItemCount = messages.count
359374
if let messageID = messages.last?.messageId, let rowID = MessageDAO.shared.messageRowID(messageID: messageID) {
360375
nextPrimaryID = "\(rowID)"
@@ -365,6 +380,9 @@ extension DeviceTransferServerDataSource {
365380
var messageItems = [TransferItem]()
366381
var transcriptMessageItems = [TransferItem]()
367382
for message in messages {
383+
guard filter.isValidItem(conversationID: message.conversationId) else {
384+
continue
385+
}
368386
if let fromDate, message.createdAt < fromDate {
369387
continue
370388
}
@@ -395,11 +413,14 @@ extension DeviceTransferServerDataSource {
395413
case .messageMention:
396414
let messageMentions = MessageMentionDAO.shared.messageMentions(limit: limit,
397415
after: location.primaryID,
398-
matching: conversationIDs)
416+
matching: conversationIDsForFetching)
399417
databaseItemCount = messageMentions.count
400418
nextPrimaryID = messageMentions.last?.messageId
401419
nextSecondaryID = nil
402420
transferItems = messageMentions.compactMap { messageMention in
421+
guard filter.isValidItem(conversationID: messageMention.conversationId) else {
422+
return nil
423+
}
403424
let deviceTransferMessageMention = DeviceTransferMessageMention(messageMention: messageMention)
404425
do {
405426
let outputData = try DeviceTransferProtocol.output(type: location.type, data: deviceTransferMessageMention, key: key)

Mixin/UserInterface/Controllers/DeviceTransfer/DeviceTransferFilter.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ struct DeviceTransferFilter {
3333
}
3434
}
3535

36+
var idsForFetching: [String]? {
37+
switch self {
38+
case .all:
39+
return nil
40+
case .designated(let ids):
41+
return ids.count > UserDatabaseDAO.strideForDeviceTransfer ? nil : ids
42+
}
43+
}
44+
3645
}
3746

3847
enum Time {
@@ -93,4 +102,12 @@ struct DeviceTransferFilter {
93102
}
94103
}
95104

105+
func isValidItem(conversationID: String) -> Bool {
106+
if case .designated(let ids) = conversation, ids.count > UserDatabaseDAO.strideForDeviceTransfer {
107+
return ids.contains(conversationID)
108+
} else {
109+
return true
110+
}
111+
}
112+
96113
}

MixinServices/MixinServices/Database/User/DAO/ConversationDAO.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -674,13 +674,21 @@ public final class ConversationDAO: UserDatabaseDAO {
674674
}
675675

676676
public func conversationsCount(matching conversationIDs: [String]?) -> Int {
677-
var sql = "SELECT COUNT(*) FROM conversations"
678677
if let conversationIDs {
679-
let ids = conversationIDs.joined(separator: "', '")
680-
sql += " WHERE conversation_id IN ('\(ids)')"
678+
var totalCount = 0
679+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
680+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
681+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
682+
let sql = "SELECT COUNT(*) FROM conversations WHERE conversation_id in ('\(ids)')"
683+
let count: Int? = db.select(with: sql)
684+
totalCount += (count ?? 0)
685+
}
686+
return totalCount
687+
} else {
688+
let sql = "SELECT COUNT(*) FROM conversations"
689+
let count: Int? = db.select(with: sql)
690+
return count ?? 0
681691
}
682-
let count: Int? = db.select(with: sql)
683-
return count ?? 0
684692
}
685693

686694
public func save(conversation: Conversation) {

MixinServices/MixinServices/Database/User/DAO/MessageDAO.swift

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -999,45 +999,77 @@ extension MessageDAO {
999999
}
10001000

10011001
public func messagesCount(matching conversationIDs: [String]?, after rowID: Int?) -> Int {
1002-
var sql = "SELECT COUNT(*) FROM messages"
1003-
if let rowID {
1004-
sql += " WHERE ROWID >= \(rowID)"
1005-
}
10061002
if let conversationIDs {
1007-
let ids = conversationIDs.joined(separator: "', '")
1008-
sql += rowID == nil ? " WHERE " : " AND "
1009-
sql += "conversation_id IN ('\(ids)')"
1003+
var totalCount = 0
1004+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
1005+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
1006+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
1007+
var sql = "SELECT COUNT(*) FROM messages WHERE conversation_id in ('\(ids)')"
1008+
if let rowID {
1009+
sql += " AND ROWID >= \(rowID)"
1010+
}
1011+
let count: Int? = db.select(with: sql)
1012+
totalCount += (count ?? 0)
1013+
}
1014+
return totalCount
1015+
} else {
1016+
var sql = "SELECT COUNT(*) FROM messages"
1017+
if let rowID {
1018+
sql += " WHERE ROWID >= \(rowID)"
1019+
}
1020+
let count: Int? = db.select(with: sql)
1021+
return count ?? 0
10101022
}
1011-
let count: Int? = db.select(with: sql)
1012-
return count ?? 0
10131023
}
10141024

10151025
public func mediaMessagesCount(matching conversationIDs: [String]?, after rowID: Int?) -> Int {
10161026
let categories = MessageCategory.allMediaCategories.map(\.rawValue).joined(separator: "', '")
1017-
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)') AND media_status IN ('DONE', 'READ')"
1018-
if let rowID {
1019-
sql += " AND ROWID >= \(rowID)"
1020-
}
10211027
if let conversationIDs {
1022-
let ids = conversationIDs.joined(separator: "', '")
1023-
sql += " AND conversation_id IN ('\(ids)')"
1028+
var totalCount = 0
1029+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
1030+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
1031+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
1032+
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)') AND media_status IN ('DONE', 'READ') AND conversation_id in ('\(ids)')"
1033+
if let rowID {
1034+
sql += " AND ROWID >= \(rowID)"
1035+
}
1036+
let count: Int? = db.select(with: sql)
1037+
totalCount += (count ?? 0)
1038+
}
1039+
return totalCount
1040+
} else {
1041+
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)') AND media_status IN ('DONE', 'READ')"
1042+
if let rowID {
1043+
sql += " AND ROWID >= \(rowID)"
1044+
}
1045+
let count: Int? = db.select(with: sql)
1046+
return count ?? 0
10241047
}
1025-
let count: Int? = db.select(with: sql)
1026-
return count ?? 0
10271048
}
10281049

10291050
public func transcriptMessageCount(matching conversationIDs: [String]?, after rowID: Int?) -> Int {
10301051
let categories = MessageCategory.transcriptCategories.map(\.rawValue).joined(separator: "', '")
1031-
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)')"
1032-
if let rowID {
1033-
sql += " AND ROWID >= \(rowID)"
1034-
}
10351052
if let conversationIDs {
1036-
let ids = conversationIDs.joined(separator: "', '")
1037-
sql += " AND conversation_id IN ('\(ids)')"
1053+
var totalCount = 0
1054+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
1055+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
1056+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
1057+
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)') AND conversation_id in ('\(ids)')"
1058+
if let rowID {
1059+
sql += " AND ROWID >= \(rowID)"
1060+
}
1061+
let count: Int? = db.select(with: sql)
1062+
totalCount += (count ?? 0)
1063+
}
1064+
return totalCount
1065+
} else {
1066+
var sql = "SELECT COUNT(*) FROM messages WHERE category IN ('\(categories)')"
1067+
if let rowID {
1068+
sql += " AND ROWID >= \(rowID)"
1069+
}
1070+
let count: Int? = db.select(with: sql)
1071+
return count ?? 0
10381072
}
1039-
let count: Int? = db.select(with: sql)
1040-
return count ?? 0
10411073
}
10421074

10431075
public func lastMessageCreatedAt() -> String? {

MixinServices/MixinServices/Database/User/DAO/MessageMentionDAO.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,20 @@ public final class MessageMentionDAO: UserDatabaseDAO {
3030
}
3131

3232
public func messageMentionsCount(matching conversationIDs: [String]?) -> Int {
33-
var sql = "SELECT COUNT(*) FROM message_mentions"
3433
if let conversationIDs {
35-
let ids = conversationIDs.joined(separator: "', '")
36-
sql += " WHERE conversation_id IN ('\(ids)')"
34+
var totalCount = 0
35+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
36+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
37+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
38+
let sql = "SELECT COUNT(*) FROM message_mentions WHERE conversation_id in ('\(ids)')"
39+
let count: Int? = db.select(with: sql)
40+
totalCount += (count ?? 0)
41+
}
42+
return totalCount
43+
} else {
44+
let count: Int? = db.select(with: "SELECT COUNT(*) FROM message_mentions")
45+
return count ?? 0
3746
}
38-
let count: Int? = db.select(with: sql)
39-
return count ?? 0
4047
}
4148

4249
public func save(messageMention: MessageMention) {

MixinServices/MixinServices/Database/User/DAO/ParticipantDAO.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,20 @@ public final class ParticipantDAO: UserDatabaseDAO {
190190
}
191191

192192
public func participantsCount(matching conversationIDs: [String]?) -> Int {
193-
var sql = "SELECT COUNT(*) FROM participants"
194193
if let conversationIDs {
195-
let ids = conversationIDs.joined(separator: "', '")
196-
sql += " WHERE conversation_id IN ('\(ids)')"
194+
var totalCount = 0
195+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
196+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
197+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
198+
let sql = "SELECT COUNT(*) FROM participants WHERE conversation_id in ('\(ids)')"
199+
let count: Int? = db.select(with: sql)
200+
totalCount += (count ?? 0)
201+
}
202+
return totalCount
203+
} else {
204+
let count: Int? = db.select(with: "SELECT COUNT(*) FROM participants")
205+
return count ?? 0
197206
}
198-
let count: Int? = db.select(with: sql)
199-
return count ?? 0
200207
}
201208

202209
public func save(participant: Participant) {

MixinServices/MixinServices/Database/User/DAO/PinMessageDAO.swift

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,27 @@ public final class PinMessageDAO: UserDatabaseDAO {
124124
}
125125

126126
public func pinMessagesCount(matching conversationIDs: [String]?, after rowID: Int?) -> Int {
127-
var sql = "SELECT COUNT(*) FROM pin_messages"
128-
if let rowID {
129-
sql += " WHERE ROWID >= \(rowID)"
130-
}
131127
if let conversationIDs {
132-
let ids = conversationIDs.joined(separator: "', '")
133-
sql += rowID == nil ? " WHERE " : " AND "
134-
sql += "conversation_id IN ('\(ids)')"
128+
var totalCount = 0
129+
for i in stride(from: 0, to: conversationIDs.count, by: Self.strideForDeviceTransfer) {
130+
let endIndex = min(i + Self.strideForDeviceTransfer, conversationIDs.count)
131+
let ids = Array(conversationIDs[i..<endIndex]).joined(separator: "', '")
132+
var sql = "SELECT COUNT(*) FROM pin_messages WHERE conversation_id in ('\(ids)')"
133+
if let rowID {
134+
sql += " AND ROWID >= \(rowID)"
135+
}
136+
let count: Int? = db.select(with: sql)
137+
totalCount += (count ?? 0)
138+
}
139+
return totalCount
140+
} else {
141+
var sql = "SELECT COUNT(*) FROM pin_messages"
142+
if let rowID {
143+
sql += " WHERE ROWID >= \(rowID)"
144+
}
145+
let count: Int? = db.select(with: sql)
146+
return count ?? 0
135147
}
136-
let count: Int? = db.select(with: sql)
137-
return count ?? 0
138148
}
139149

140150
public func messageRowID(createdAt: String) -> Int? {

MixinServices/MixinServices/Database/User/UserDatabaseDAO.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@ public class UserDatabaseDAO {
77
}
88

99
}
10+
11+
extension UserDatabaseDAO {
12+
13+
// To prevent excessive memory allocations,
14+
// the maximum value of a host parameter number is SQLITE_MAX_VARIABLE_NUMBER,
15+
// which defaults to 999 for SQLite versions prior to 3.32.0 (2020-05-22) or 32766 for SQLite versions after 3.32.0.
16+
// Therefore, we default to grouping with 900
17+
public static let strideForDeviceTransfer = 900
18+
19+
}

0 commit comments

Comments
 (0)