Fix Lint issues.
This commit is contained in:
parent
cbea8acd9a
commit
aea89148ff
@ -13,7 +13,7 @@ let package = Package(
|
||||
.library(
|
||||
name: "RSDatabaseObjC",
|
||||
type: .dynamic,
|
||||
targets: ["RSDatabaseObjC"]),
|
||||
targets: ["RSDatabaseObjC"])
|
||||
],
|
||||
dependencies: [
|
||||
],
|
||||
@ -29,6 +29,6 @@ let package = Package(
|
||||
),
|
||||
.testTarget(
|
||||
name: "RSDatabaseTests",
|
||||
dependencies: ["RSDatabase"]),
|
||||
dependencies: ["RSDatabase"])
|
||||
]
|
||||
)
|
||||
|
@ -20,9 +20,9 @@ public protocol DatabaseObject {
|
||||
}
|
||||
|
||||
public extension DatabaseObject {
|
||||
|
||||
|
||||
func relatedObjectsWithName(_ name: String) -> [DatabaseObject]? {
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -37,14 +37,14 @@ extension Array where Element == DatabaseObject {
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
|
||||
func databaseIDs() -> Set<String> {
|
||||
|
||||
|
||||
return Set(self.map { $0.databaseID })
|
||||
}
|
||||
|
||||
|
||||
func includesObjectWithDatabaseID(_ databaseID: String) -> Bool {
|
||||
|
||||
|
||||
for object in self {
|
||||
if object.databaseID == databaseID {
|
||||
return true
|
||||
@ -55,7 +55,7 @@ extension Array where Element == DatabaseObject {
|
||||
|
||||
func databaseDictionaries() -> [DatabaseDictionary]? {
|
||||
|
||||
let dictionaries = self.compactMap{ $0.databaseDictionary() }
|
||||
let dictionaries = self.compactMap { $0.databaseDictionary() }
|
||||
return dictionaries.isEmpty ? nil : dictionaries
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ public final class DatabaseQueue {
|
||||
/// Use this to create tables, indexes, etc.
|
||||
public func runCreateStatements(_ statements: String) throws {
|
||||
precondition(Thread.isMainThread)
|
||||
var error: DatabaseError? = nil
|
||||
var error: DatabaseError?
|
||||
runInDatabaseSync { result in
|
||||
switch result {
|
||||
case .success(let database):
|
||||
@ -236,8 +236,7 @@ private extension DatabaseQueue {
|
||||
autoreleasepool {
|
||||
if _isSuspended {
|
||||
databaseBlock(.failure(.isSuspended))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if useTransaction {
|
||||
database.beginTransaction()
|
||||
}
|
||||
@ -256,4 +255,3 @@ private extension DatabaseQueue {
|
||||
database.setShouldCacheStatements(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,11 @@ public protocol DatabaseTable {
|
||||
}
|
||||
|
||||
public extension DatabaseTable {
|
||||
|
||||
|
||||
// MARK: Fetching
|
||||
|
||||
func selectRowsWhere(key: String, equals value: Any, in database: FMDatabase) -> FMResultSet? {
|
||||
|
||||
|
||||
return database.rs_selectRowsWhereKey(key, equalsValue: value, tableName: name)
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ public extension DatabaseTable {
|
||||
// MARK: Deleting
|
||||
|
||||
func deleteRowsWhere(key: String, equalsAnyValue values: [Any], in database: FMDatabase) {
|
||||
|
||||
|
||||
if values.isEmpty {
|
||||
return
|
||||
}
|
||||
@ -49,21 +49,21 @@ public extension DatabaseTable {
|
||||
// MARK: Updating
|
||||
|
||||
func updateRowsWithValue(_ value: Any, valueKey: String, whereKey: String, matches: [Any], database: FMDatabase) {
|
||||
|
||||
let _ = database.rs_updateRows(withValue: value, valueKey: valueKey, whereKey: whereKey, inValues: matches, tableName: self.name)
|
||||
|
||||
_ = database.rs_updateRows(withValue: value, valueKey: valueKey, whereKey: whereKey, inValues: matches, tableName: self.name)
|
||||
}
|
||||
|
||||
|
||||
func updateRowsWithDictionary(_ dictionary: DatabaseDictionary, whereKey: String, matches: Any, database: FMDatabase) {
|
||||
|
||||
let _ = database.rs_updateRows(with: dictionary, whereKey: whereKey, equalsValue: matches, tableName: self.name)
|
||||
|
||||
_ = database.rs_updateRows(with: dictionary, whereKey: whereKey, equalsValue: matches, tableName: self.name)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Saving
|
||||
|
||||
func insertRows(_ dictionaries: [DatabaseDictionary], insertType: RSDatabaseInsertType, in database: FMDatabase) {
|
||||
|
||||
for oneDictionary in dictionaries {
|
||||
let _ = database.rs_insertRow(with: oneDictionary, insertType: insertType, tableName: self.name)
|
||||
_ = database.rs_insertRow(with: oneDictionary, insertType: insertType, tableName: self.name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,4 +136,3 @@ public extension FMResultSet {
|
||||
return Set(compactMap(completion))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ public final class DatabaseLookupTable {
|
||||
private let relationshipName: String
|
||||
private let relatedTable: DatabaseRelatedObjectsTable
|
||||
private var objectIDsWithNoRelatedObjects = Set<String>()
|
||||
|
||||
|
||||
public init(name: String, objectIDKey: String, relatedObjectIDKey: String, relatedTable: DatabaseRelatedObjectsTable, relationshipName: String) {
|
||||
|
||||
self.name = name
|
||||
@ -32,47 +32,46 @@ public final class DatabaseLookupTable {
|
||||
}
|
||||
|
||||
public func fetchRelatedObjects(for objectIDs: Set<String>, in database: FMDatabase) -> RelatedObjectsMap? {
|
||||
|
||||
|
||||
let objectIDsThatMayHaveRelatedObjects = objectIDs.subtracting(objectIDsWithNoRelatedObjects)
|
||||
if objectIDsThatMayHaveRelatedObjects.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
guard let relatedObjectIDsMap = fetchRelatedObjectIDsMap(objectIDsThatMayHaveRelatedObjects, database) else {
|
||||
objectIDsWithNoRelatedObjects.formUnion(objectIDsThatMayHaveRelatedObjects)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
if let relatedObjects = fetchRelatedObjectsWithIDs(relatedObjectIDsMap.relatedObjectIDs(), database) {
|
||||
|
||||
|
||||
let relatedObjectsMap = RelatedObjectsMap(relatedObjects: relatedObjects, relatedObjectIDsMap: relatedObjectIDsMap)
|
||||
|
||||
|
||||
let objectIDsWithNoFetchedRelatedObjects = objectIDsThatMayHaveRelatedObjects.subtracting(relatedObjectsMap.objectIDs())
|
||||
objectIDsWithNoRelatedObjects.formUnion(objectIDsWithNoFetchedRelatedObjects)
|
||||
|
||||
|
||||
return relatedObjectsMap
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
public func saveRelatedObjects(for objects: [DatabaseObject], in database: FMDatabase) {
|
||||
|
||||
|
||||
var objectsWithNoRelationships = [DatabaseObject]()
|
||||
var objectsWithRelationships = [DatabaseObject]()
|
||||
|
||||
for object in objects {
|
||||
if let relatedObjects = object.relatedObjectsWithName(relationshipName), !relatedObjects.isEmpty {
|
||||
objectsWithRelationships += [object]
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
objectsWithNoRelationships += [object]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
removeRelationships(for: objectsWithNoRelationships, database)
|
||||
updateRelationships(for: objectsWithRelationships, database)
|
||||
|
||||
|
||||
objectIDsWithNoRelatedObjects.formUnion(objectsWithNoRelationships.databaseIDs())
|
||||
objectIDsWithNoRelatedObjects.subtract(objectsWithRelationships.databaseIDs())
|
||||
}
|
||||
@ -83,7 +82,7 @@ public final class DatabaseLookupTable {
|
||||
private extension DatabaseLookupTable {
|
||||
|
||||
// MARK: Removing
|
||||
|
||||
|
||||
func removeRelationships(for objects: [DatabaseObject], _ database: FMDatabase) {
|
||||
|
||||
let objectIDs = objects.databaseIDs()
|
||||
@ -91,52 +90,52 @@ private extension DatabaseLookupTable {
|
||||
if objectIDsToRemove.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
database.rs_deleteRowsWhereKey(objectIDKey, inValues: Array(objectIDsToRemove), tableName: name)
|
||||
}
|
||||
|
||||
|
||||
func deleteLookups(for objectID: String, _ relatedObjectIDs: Set<String>, _ database: FMDatabase) {
|
||||
|
||||
|
||||
guard !relatedObjectIDs.isEmpty else {
|
||||
assertionFailure("deleteLookups: expected non-empty relatedObjectIDs")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// delete from authorLookup where articleID=? and authorID in (?,?,?)
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(relatedObjectIDs.count))!
|
||||
let sql = "delete from \(name) where \(objectIDKey)=? and \(relatedObjectIDKey) in \(placeholders)"
|
||||
|
||||
|
||||
let parameters: [Any] = [objectID] + Array(relatedObjectIDs)
|
||||
let _ = database.executeUpdate(sql, withArgumentsIn: parameters)
|
||||
_ = database.executeUpdate(sql, withArgumentsIn: parameters)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Saving/Updating
|
||||
|
||||
|
||||
func updateRelationships(for objects: [DatabaseObject], _ database: FMDatabase) {
|
||||
|
||||
if objects.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if let lookupTable = fetchRelatedObjectIDsMap(objects.databaseIDs(), database) {
|
||||
for object in objects {
|
||||
syncRelatedObjectsAndLookupTable(object, lookupTable, database)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Save the actual related objects.
|
||||
|
||||
|
||||
let relatedObjectsToSave = uniqueArrayOfRelatedObjects(with: objects)
|
||||
if relatedObjectsToSave.isEmpty {
|
||||
assertionFailure("updateRelationships: expected relatedObjectsToSave would not be empty. This should be unreachable.")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
relatedTable.save(relatedObjectsToSave, in: database)
|
||||
}
|
||||
|
||||
func uniqueArrayOfRelatedObjects(with objects: [DatabaseObject]) -> [DatabaseObject] {
|
||||
|
||||
|
||||
// Can’t create a Set, because we can’t make a Set<DatabaseObject>, because protocol-conforming objects can’t be made Hashable or even Equatable.
|
||||
// We still want the array to include only one copy of each object, but we have to do it the slow way. Instruments will tell us if this is a performance problem.
|
||||
|
||||
@ -154,48 +153,48 @@ private extension DatabaseLookupTable {
|
||||
}
|
||||
return relatedObjectsUniqueArray
|
||||
}
|
||||
|
||||
|
||||
func syncRelatedObjectsAndLookupTable(_ object: DatabaseObject, _ lookupTable: RelatedObjectIDsMap, _ database: FMDatabase) {
|
||||
|
||||
|
||||
guard let relatedObjects = object.relatedObjectsWithName(relationshipName) else {
|
||||
assertionFailure("syncRelatedObjectsAndLookupTable should be called only on objects with related objects.")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let relatedObjectIDs = relatedObjects.databaseIDs()
|
||||
let lookupTableRelatedObjectIDs = lookupTable[object.databaseID] ?? Set<String>()
|
||||
|
||||
|
||||
let relatedObjectIDsToDelete = lookupTableRelatedObjectIDs.subtracting(relatedObjectIDs)
|
||||
if !relatedObjectIDsToDelete.isEmpty {
|
||||
deleteLookups(for: object.databaseID, relatedObjectIDsToDelete, database)
|
||||
}
|
||||
|
||||
|
||||
let relatedObjectIDsToSave = relatedObjectIDs.subtracting(lookupTableRelatedObjectIDs)
|
||||
if !relatedObjectIDsToSave.isEmpty {
|
||||
saveLookups(for: object.databaseID, relatedObjectIDsToSave, database)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func saveLookups(for objectID: String, _ relatedObjectIDs: Set<String>, _ database: FMDatabase) {
|
||||
|
||||
|
||||
for relatedObjectID in relatedObjectIDs {
|
||||
let d: [NSObject: Any] = [(objectIDKey as NSString): objectID, (relatedObjectIDKey as NSString): relatedObjectID]
|
||||
let _ = database.rs_insertRow(with: d, insertType: .orIgnore, tableName: name)
|
||||
_ = database.rs_insertRow(with: d, insertType: .orIgnore, tableName: name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Fetching
|
||||
|
||||
|
||||
func fetchRelatedObjectsWithIDs(_ relatedObjectIDs: Set<String>, _ database: FMDatabase) -> [DatabaseObject]? {
|
||||
|
||||
|
||||
guard let relatedObjects = relatedTable.fetchObjectsWithIDs(relatedObjectIDs, in: database), !relatedObjects.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
return relatedObjects
|
||||
}
|
||||
|
||||
|
||||
func fetchRelatedObjectIDsMap(_ objectIDs: Set<String>, _ database: FMDatabase) -> RelatedObjectIDsMap? {
|
||||
|
||||
|
||||
guard let lookupValues = fetchLookupValues(objectIDs, database) else {
|
||||
return nil
|
||||
}
|
||||
@ -203,20 +202,20 @@ private extension DatabaseLookupTable {
|
||||
}
|
||||
|
||||
func fetchLookupValues(_ objectIDs: Set<String>, _ database: FMDatabase) -> Set<LookupValue>? {
|
||||
|
||||
|
||||
guard !objectIDs.isEmpty, let resultSet = database.rs_selectRowsWhereKey(objectIDKey, inValues: Array(objectIDs), tableName: name) else {
|
||||
return nil
|
||||
}
|
||||
return lookupValuesWithResultSet(resultSet)
|
||||
}
|
||||
|
||||
|
||||
func lookupValuesWithResultSet(_ resultSet: FMResultSet) -> Set<LookupValue> {
|
||||
|
||||
|
||||
return resultSet.mapToSet(lookupValueWithRow)
|
||||
}
|
||||
|
||||
|
||||
func lookupValueWithRow(_ row: FMResultSet) -> LookupValue? {
|
||||
|
||||
|
||||
guard let objectID = row.string(forColumn: objectIDKey) else {
|
||||
return nil
|
||||
}
|
||||
@ -226,4 +225,3 @@ private extension DatabaseLookupTable {
|
||||
return LookupValue(objectID: objectID, relatedObjectID: relatedObjectID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public protocol DatabaseRelatedObjectsTable: DatabaseTable {
|
||||
|
||||
var databaseIDKey: String { get}
|
||||
var cache: DatabaseObjectCache { get }
|
||||
|
||||
|
||||
func fetchObjectsWithIDs(_ databaseIDs: Set<String>, in database: FMDatabase) -> [DatabaseObject]?
|
||||
func objectsWithResultSet(_ resultSet: FMResultSet) -> [DatabaseObject]
|
||||
func objectWithRow(_ row: FMResultSet) -> DatabaseObject?
|
||||
@ -39,8 +39,7 @@ public extension DatabaseRelatedObjectsTable {
|
||||
for databaseID in databaseIDs {
|
||||
if let cachedObject = cache[databaseID] {
|
||||
cachedObjects += [cachedObject]
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
databaseIDsToFetch.insert(databaseID)
|
||||
}
|
||||
}
|
||||
|
@ -11,46 +11,45 @@ import Foundation
|
||||
// Maps objectIDs to Set<String> where the Strings are relatedObjectIDs.
|
||||
|
||||
struct RelatedObjectIDsMap {
|
||||
|
||||
|
||||
private let dictionary: [String: Set<String>] // objectID: Set<relatedObjectID>
|
||||
|
||||
|
||||
init(dictionary: [String: Set<String>]) {
|
||||
|
||||
|
||||
self.dictionary = dictionary
|
||||
}
|
||||
|
||||
|
||||
init(lookupValues: Set<LookupValue>) {
|
||||
|
||||
|
||||
var d = [String: Set<String>]()
|
||||
|
||||
|
||||
for lookupValue in lookupValues {
|
||||
let objectID = lookupValue.objectID
|
||||
let relatedObjectID: String = lookupValue.relatedObjectID
|
||||
if d[objectID] == nil {
|
||||
d[objectID] = Set([relatedObjectID])
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
d[objectID]!.insert(relatedObjectID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.init(dictionary: d)
|
||||
}
|
||||
|
||||
|
||||
func objectIDs() -> Set<String> {
|
||||
|
||||
|
||||
return Set(dictionary.keys)
|
||||
}
|
||||
|
||||
|
||||
func relatedObjectIDs() -> Set<String> {
|
||||
|
||||
|
||||
var ids = Set<String>()
|
||||
for (_, relatedObjectIDs) in dictionary {
|
||||
ids.formUnion(relatedObjectIDs)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
|
||||
subscript(_ objectID: String) -> Set<String>? {
|
||||
return dictionary[objectID]
|
||||
}
|
||||
|
@ -12,32 +12,32 @@ import Foundation
|
||||
// It’s used as the return value for DatabaseLookupTable.fetchRelatedObjects.
|
||||
|
||||
public struct RelatedObjectsMap {
|
||||
|
||||
|
||||
private let dictionary: [String: [DatabaseObject]] // objectID: relatedObjects
|
||||
|
||||
|
||||
init(relatedObjects: [DatabaseObject], relatedObjectIDsMap: RelatedObjectIDsMap) {
|
||||
|
||||
|
||||
var d = [String: [DatabaseObject]]()
|
||||
let relatedObjectsDictionary = relatedObjects.dictionary()
|
||||
|
||||
|
||||
for objectID in relatedObjectIDsMap.objectIDs() {
|
||||
|
||||
|
||||
if let relatedObjectIDs = relatedObjectIDsMap[objectID] {
|
||||
let relatedObjects = relatedObjectIDs.compactMap{ relatedObjectsDictionary[$0] }
|
||||
let relatedObjects = relatedObjectIDs.compactMap { relatedObjectsDictionary[$0] }
|
||||
if !relatedObjects.isEmpty {
|
||||
d[objectID] = relatedObjects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
self.dictionary = d
|
||||
}
|
||||
|
||||
|
||||
public func objectIDs() -> Set<String> {
|
||||
|
||||
|
||||
return Set(dictionary.keys)
|
||||
}
|
||||
|
||||
|
||||
public subscript(_ objectID: String) -> [DatabaseObject]? {
|
||||
return dictionary[objectID]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user