// // DatabaseRelatedObjectsTable.swift // RSDatabase // // Created by Brent Simmons on 9/2/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. // import Foundation // Protocol for a database table for related objects — authors and attachments in Evergreen, for instance. public protocol DatabaseRelatedObjectsTable: DatabaseTable { var databaseIDKey: String { get} var cache: DatabaseObjectCache { get } func fetchObjectsWithIDs(_ databaseIDs: Set, in database: FMDatabase) -> [DatabaseObject]? func objectsWithResultSet(_ resultSet: FMResultSet) -> [DatabaseObject] func objectWithRow(_ row: FMResultSet) -> DatabaseObject? func save(_ objects: [DatabaseObject], in database: FMDatabase) } public extension DatabaseRelatedObjectsTable { // MARK: Default implementations func fetchObjectsWithIDs(_ databaseIDs: Set, in database: FMDatabase) -> [DatabaseObject]? { if databaseIDs.isEmpty { return nil } var cachedObjects = [DatabaseObject]() var databaseIDsToFetch = Set() for databaseID in databaseIDs { if let cachedObject = cache[databaseID] { cachedObjects += [cachedObject] } else { databaseIDsToFetch.insert(databaseID) } } if databaseIDsToFetch.isEmpty { return cachedObjects } guard let resultSet = selectRowsWhere(key: databaseIDKey, inValues: Array(databaseIDsToFetch), in: database) else { return cachedObjects } let fetchedDatabaseObjects = objectsWithResultSet(resultSet) cache.add(fetchedDatabaseObjects) return cachedObjects + fetchedDatabaseObjects } func objectsWithResultSet(_ resultSet: FMResultSet) -> [DatabaseObject] { return resultSet.compactMap(objectWithRow) } func save(_ objects: [DatabaseObject], in database: FMDatabase) { // Objects in cache must already exist in database. Filter them out. let objectsToSave = objects.filter { (object) -> Bool in if let _ = cache[object.databaseID] { return false } return true } cache.add(objectsToSave) if let databaseDictionaries = objectsToSave.databaseDictionaries() { insertRows(databaseDictionaries, insertType: .orIgnore, in: database) } } }