2017-09-02 19:11:19 +02:00
|
|
|
|
//
|
|
|
|
|
// DatabaseRelatedObjectsTable.swift
|
|
|
|
|
// RSDatabase
|
|
|
|
|
//
|
|
|
|
|
// Created by Brent Simmons on 9/2/17.
|
|
|
|
|
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
|
|
2017-12-19 03:20:13 +01:00
|
|
|
|
// Protocol for a database table for related objects — authors and attachments in Evergreen, for instance.
|
2017-09-11 22:11:29 +02:00
|
|
|
|
|
2017-09-02 19:11:19 +02:00
|
|
|
|
public protocol DatabaseRelatedObjectsTable: DatabaseTable {
|
|
|
|
|
|
|
|
|
|
var databaseIDKey: String { get}
|
2017-09-13 06:47:04 +02:00
|
|
|
|
var cache: DatabaseObjectCache { get }
|
|
|
|
|
|
2017-09-13 06:19:45 +02:00
|
|
|
|
func fetchObjectsWithIDs(_ databaseIDs: Set<String>, in database: FMDatabase) -> [DatabaseObject]?
|
2017-09-02 19:11:19 +02:00
|
|
|
|
func objectsWithResultSet(_ resultSet: FMResultSet) -> [DatabaseObject]
|
|
|
|
|
func objectWithRow(_ row: FMResultSet) -> DatabaseObject?
|
|
|
|
|
|
|
|
|
|
func save(_ objects: [DatabaseObject], in database: FMDatabase)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public extension DatabaseRelatedObjectsTable {
|
|
|
|
|
|
|
|
|
|
// MARK: Default implementations
|
|
|
|
|
|
2017-09-13 06:19:45 +02:00
|
|
|
|
func fetchObjectsWithIDs(_ databaseIDs: Set<String>, in database: FMDatabase) -> [DatabaseObject]? {
|
2017-09-02 19:11:19 +02:00
|
|
|
|
|
2017-09-13 06:47:04 +02:00
|
|
|
|
if databaseIDs.isEmpty {
|
2017-09-13 06:19:45 +02:00
|
|
|
|
return nil
|
2017-09-02 19:11:19 +02:00
|
|
|
|
}
|
2017-09-13 06:47:04 +02:00
|
|
|
|
|
|
|
|
|
var cachedObjects = [DatabaseObject]()
|
|
|
|
|
var databaseIDsToFetch = Set<String>()
|
|
|
|
|
|
|
|
|
|
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
|
2017-09-02 19:11:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func objectsWithResultSet(_ resultSet: FMResultSet) -> [DatabaseObject] {
|
|
|
|
|
|
2018-01-28 03:50:48 +01:00
|
|
|
|
return resultSet.compactMap(objectWithRow)
|
2017-09-02 19:11:19 +02:00
|
|
|
|
}
|
2017-09-13 22:29:52 +02:00
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-02 19:11:19 +02:00
|
|
|
|
}
|