mirror of
https://github.com/signalapp/Signal-iOS.git
synced 2025-12-05 01:10:41 +00:00
Cache the TSInteraction insert statement for backup restore.
This commit is contained in:
@@ -1128,7 +1128,8 @@ def generate_swift_extensions_for_model(clazz):
|
||||
return
|
||||
|
||||
has_sds_superclass = clazz.has_sds_superclass()
|
||||
has_remove_methods = clazz.name not in ("TSThread","TSInteraction")
|
||||
has_remove_methods = clazz.name not in ("TSThread", "TSInteraction")
|
||||
has_grdb_serializer = clazz.name in ("TSInteraction")
|
||||
|
||||
swift_filename = os.path.basename(clazz.filepath)
|
||||
swift_filename = swift_filename[: swift_filename.find(".")] + "+SDS.swift"
|
||||
@@ -1758,6 +1759,43 @@ extension %(class_name)s: DeepCopyable {
|
||||
swift_body += """
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
if has_grdb_serializer:
|
||||
swift_body += """
|
||||
// MARK: - Table Metadata
|
||||
|
||||
extension %sRecord {
|
||||
|
||||
// This defines all of the columns used in the table
|
||||
// where this model (and any subclasses) are persisted.
|
||||
internal func asArguments() -> StatementArguments {
|
||||
let databaseValues: [DatabaseValueConvertible?] = [
|
||||
""" % str(
|
||||
remove_prefix_from_class_name(clazz.name)
|
||||
)
|
||||
|
||||
def write_grdb_column_metadata(property):
|
||||
# column_name = property.swift_identifier()
|
||||
column_name = property.column_name()
|
||||
return """ %s,
|
||||
""" % (
|
||||
str(column_name)
|
||||
)
|
||||
|
||||
for property in sds_properties:
|
||||
if property.name != "id":
|
||||
swift_body += write_grdb_column_metadata(property)
|
||||
|
||||
if len(record_properties) > 0:
|
||||
for property in record_properties:
|
||||
swift_body += write_grdb_column_metadata(property)
|
||||
|
||||
swift_body += """
|
||||
]
|
||||
return StatementArguments(databaseValues)
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
if not has_sds_superclass:
|
||||
@@ -1817,7 +1855,9 @@ extension %sSerializer {
|
||||
SDSTableMetadata(
|
||||
tableName: "%s",
|
||||
columns: [
|
||||
""" % (database_table_name,)
|
||||
""" % (
|
||||
database_table_name,
|
||||
)
|
||||
swift_body += "\n".join(
|
||||
[
|
||||
" %sColumn," % str(column_property_name)
|
||||
|
||||
@@ -30,6 +30,9 @@ public final class MessageBackupInteractionStore {
|
||||
{}
|
||||
}
|
||||
|
||||
// Even generating the sql string itself is expensive when multiplied by 200k messages.
|
||||
// So we generate the string once and cache it (on top of caching the Statement)
|
||||
private var cachedSQL: String?
|
||||
func insert(
|
||||
_ interaction: TSInteraction,
|
||||
in thread: MessageBackup.ChatThread,
|
||||
@@ -67,7 +70,23 @@ public final class MessageBackupInteractionStore {
|
||||
// and restore, we'll only send back a Null message. (Until such a day
|
||||
// when resends use the interactions table and not MSL at all).
|
||||
|
||||
try interaction.asRecord().insert(context.tx.databaseConnection)
|
||||
let sql: String
|
||||
if let cachedSQL {
|
||||
sql = cachedSQL
|
||||
} else {
|
||||
let columnsSQL = InteractionRecord.CodingKeys.allCases.filter({ $0 != .id }).map(\.name).joined(separator: ", ")
|
||||
let valuesSQL = InteractionRecord.CodingKeys.allCases.filter({ $0 != .id }).map({ _ in "?" }).joined(separator: ", ")
|
||||
sql = """
|
||||
INSERT INTO \(InteractionRecord.databaseTableName) (\(columnsSQL)) \
|
||||
VALUES (\(valuesSQL))
|
||||
"""
|
||||
cachedSQL = sql
|
||||
}
|
||||
|
||||
let statement = try context.tx.databaseConnection.cachedStatement(sql: sql)
|
||||
try statement.setUncheckedArguments((interaction.asRecord() as! InteractionRecord).asArguments())
|
||||
try statement.execute()
|
||||
interaction.updateRowId(context.tx.databaseConnection.lastInsertedRowID)
|
||||
|
||||
guard let interactionRowId = interaction.sqliteRowId else {
|
||||
throw OWSAssertionError("Missing row id after insertion!")
|
||||
|
||||
@@ -6212,6 +6212,95 @@ extension TSInteraction: DeepCopyable {
|
||||
|
||||
// MARK: - Table Metadata
|
||||
|
||||
extension InteractionRecord {
|
||||
|
||||
// This defines all of the columns used in the table
|
||||
// where this model (and any subclasses) are persisted.
|
||||
internal func asArguments() -> StatementArguments {
|
||||
let databaseValues: [DatabaseValueConvertible?] = [
|
||||
recordType,
|
||||
uniqueId,
|
||||
receivedAtTimestamp,
|
||||
timestamp,
|
||||
threadUniqueId,
|
||||
attachmentIds,
|
||||
authorId,
|
||||
authorPhoneNumber,
|
||||
authorUUID,
|
||||
body,
|
||||
callType,
|
||||
configurationDurationSeconds,
|
||||
configurationIsEnabled,
|
||||
contactShare,
|
||||
createdByRemoteName,
|
||||
createdInExistingGroup,
|
||||
customMessage,
|
||||
envelopeData,
|
||||
errorType,
|
||||
expireStartedAt,
|
||||
expiresAt,
|
||||
expiresInSeconds,
|
||||
groupMetaMessage,
|
||||
hasLegacyMessageState,
|
||||
hasSyncedTranscript,
|
||||
wasNotCreatedLocally,
|
||||
isLocalChange,
|
||||
isViewOnceComplete,
|
||||
isViewOnceMessage,
|
||||
isVoiceMessage,
|
||||
legacyMessageState,
|
||||
legacyWasDelivered,
|
||||
linkPreview,
|
||||
messageId,
|
||||
messageSticker,
|
||||
messageType,
|
||||
mostRecentFailureText,
|
||||
preKeyBundle,
|
||||
protocolVersion,
|
||||
quotedMessage,
|
||||
read,
|
||||
recipientAddress,
|
||||
recipientAddressStates,
|
||||
sender,
|
||||
serverTimestamp,
|
||||
deprecated_sourceDeviceId,
|
||||
storedMessageState,
|
||||
storedShouldStartExpireTimer,
|
||||
unregisteredAddress,
|
||||
verificationState,
|
||||
wasReceivedByUD,
|
||||
infoMessageUserInfo,
|
||||
wasRemotelyDeleted,
|
||||
bodyRanges,
|
||||
offerType,
|
||||
serverDeliveryTimestamp,
|
||||
eraId,
|
||||
hasEnded,
|
||||
creatorUuid,
|
||||
joinedMemberUuids,
|
||||
wasIdentityVerified,
|
||||
paymentCancellation,
|
||||
paymentNotification,
|
||||
paymentRequest,
|
||||
viewed,
|
||||
serverGuid,
|
||||
storyAuthorUuidString,
|
||||
storyTimestamp,
|
||||
isGroupStoryReply,
|
||||
storyReactionEmoji,
|
||||
giftBadge,
|
||||
editState,
|
||||
archivedPaymentInfo,
|
||||
expireTimerVersion,
|
||||
isSmsMessageRestoredFromBackup,
|
||||
|
||||
]
|
||||
return StatementArguments(databaseValues)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table Metadata
|
||||
|
||||
extension TSInteractionSerializer {
|
||||
|
||||
// This defines all of the columns used in the table
|
||||
|
||||
Reference in New Issue
Block a user