Path: blob/main/SignalServiceKit/Storage/Database/SDSCodableModel/SDSCodableModelDatabaseInterface+Enumerate.swift
1 views
//
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import GRDB
public enum BatchingPreference {
case batched(UInt = Batching.kDefaultBatchSize)
case unbatched
}
extension SDSCodableModelDatabaseInterfaceImpl {
/// Traverse all records, in no particular order.
func enumerateModels<Model: SDSCodableModel>(
modelType: Model.Type,
transaction: DBReadTransaction,
batchingPreference: BatchingPreference,
block: (Model, inout Bool) -> Void,
) {
let batchSize = batchSize(batchingPreference: batchingPreference)
enumerateModels(
modelType: modelType,
transaction: transaction,
sql: nil,
arguments: nil,
batchSize: batchSize,
block: block,
)
}
/// Traverse all records, in no particular order.
func enumerateModels<Model: SDSCodableModel>(
modelType: Model.Type,
transaction: DBReadTransaction,
sql: String,
arguments: StatementArguments,
batchingPreference: BatchingPreference,
block: (Model, inout Bool) -> Void,
) {
let batchSize = batchSize(batchingPreference: batchingPreference)
enumerateModels(
modelType: modelType,
transaction: transaction,
sql: sql,
arguments: arguments,
batchSize: batchSize,
block: block,
)
}
/// The batch size for enumeration.
private func batchSize(batchingPreference: BatchingPreference) -> UInt {
switch batchingPreference {
case .batched(let size):
return size
case .unbatched:
return 0
}
}
/// Traverse all records, in no particular order.
/// - Parameter batchSize
/// If nonzero, enumeration is performed in autoreleased batches.
private func enumerateModels<Model: SDSCodableModel>(
modelType: Model.Type,
transaction: DBReadTransaction,
sql: String? = nil,
arguments: StatementArguments? = nil,
batchSize: UInt,
block: (Model, inout Bool) -> Void,
) {
failIfThrows {
var recordCursor: RecordCursor<Model>
if let sql, let arguments {
recordCursor = try Model.fetchCursor(
transaction.database,
sql: sql,
arguments: arguments,
)
} else {
recordCursor = try modelType.fetchCursor(transaction.database)
}
try Batching.loop(batchSize: batchSize) { stop in
guard let value = try recordCursor.next() else {
stop = true
return
}
value.anyDidEnumerateOne(transaction: transaction)
block(value, &stop)
}
}
}
}