Continue progress on relationships.

This commit is contained in:
Brent Simmons 2017-08-07 20:00:46 -07:00
parent 7edc76cd6e
commit 7f573c2b14
4 changed files with 49 additions and 27 deletions

View File

@ -11,11 +11,8 @@ import Foundation
public protocol DatabaseTable {
var name: String {get}
var queue: RSDatabaseQueue {get}
init(name: String, queue: RSDatabaseQueue)
func fetchObjectsWithIDs<T>(_ databaseIDs: Set<String>, _ database: FMDatabase) -> [T]
func fetchObjectsWithIDs(_ databaseIDs: Set<String>, _ database: FMDatabase) -> [DatabaseObject]
}
public extension DatabaseTable {

View File

@ -37,6 +37,7 @@
849BF8C61C94FB8E0071D1DA /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 849BF8C51C94FB8E0071D1DA /* libsqlite3.tbd */; };
84ABC1D11F364B07000DCC55 /* LookupTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84ABC1D01F364B07000DCC55 /* LookupTable.swift */; };
84ABC1D21F364B07000DCC55 /* LookupTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84ABC1D01F364B07000DCC55 /* LookupTable.swift */; };
84C6DD011F395C13009AFB47 /* DatabaseObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C6DD001F395C13009AFB47 /* DatabaseObject.swift */; };
84DDF1961C94FC45005E6CF5 /* FMDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DDF18B1C94FC45005E6CF5 /* FMDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; };
84DDF1971C94FC45005E6CF5 /* FMDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 84DDF18C1C94FC45005E6CF5 /* FMDatabase.m */; };
84DDF1981C94FC45005E6CF5 /* FMDatabaseAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DDF18D1C94FC45005E6CF5 /* FMDatabaseAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -74,6 +75,7 @@
844D97401F2D32F300CEDDEA /* ObjectCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ObjectCache.swift; path = RSDatabase/ObjectCache.swift; sourceTree = "<group>"; };
849BF8C51C94FB8E0071D1DA /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
84ABC1D01F364B07000DCC55 /* LookupTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LookupTable.swift; path = RSDatabase/LookupTable.swift; sourceTree = "<group>"; };
84C6DD001F395C13009AFB47 /* DatabaseObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DatabaseObject.swift; path = RSDatabase/DatabaseObject.swift; sourceTree = "<group>"; };
84DDF18B1C94FC45005E6CF5 /* FMDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabase.h; sourceTree = "<group>"; };
84DDF18C1C94FC45005E6CF5 /* FMDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FMDatabase.m; sourceTree = "<group>"; };
84DDF18D1C94FC45005E6CF5 /* FMDatabaseAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FMDatabaseAdditions.h; sourceTree = "<group>"; };
@ -159,6 +161,7 @@
84419AD81B5ABD7400C26BB2 /* NSString+RSDatabase.h */,
84419AD91B5ABD7400C26BB2 /* NSString+RSDatabase.m */,
840405DA1F1C158C00DF0296 /* DatabaseTable.swift */,
84C6DD001F395C13009AFB47 /* DatabaseObject.swift */,
84ABC1D01F364B07000DCC55 /* LookupTable.swift */,
844D97401F2D32F300CEDDEA /* ObjectCache.swift */,
84DDF18A1C94FC45005E6CF5 /* FMDB */,
@ -370,6 +373,7 @@
files = (
84419AE71B5ABD7F00C26BB2 /* RSDatabaseQueue.m in Sources */,
84419AD71B5ABD6D00C26BB2 /* FMDatabase+RSExtras.m in Sources */,
84C6DD011F395C13009AFB47 /* DatabaseObject.swift in Sources */,
84419ADB1B5ABD7400C26BB2 /* NSString+RSDatabase.m in Sources */,
840405DB1F1C158C00DF0296 /* DatabaseTable.swift in Sources */,
84ABC1D11F364B07000DCC55 /* LookupTable.swift in Sources */,

View File

@ -0,0 +1,28 @@
//
// DatabaseObject.swift
// RSDatabase
//
// Created by Brent Simmons on 8/7/17.
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public protocol DatabaseObject {
var databaseID: String { get }
func attachRelationshipWithObjects(_ objects: [DatabaseObject], name: String)
}
extension Array where Element == DatabaseObject {
func dictionary() -> [String: DatabaseObject] {
var d = [String: DatabaseObject]()
for object in self {
d[object.databaseID] = object
}
return d
}
}

View File

@ -17,9 +17,9 @@ import Foundation
public typealias LookupTableDictionary = [String: Set<LookupValue>] // key is foreignID
public final class LookupTable {
public final class LookupTable: DatabaseTable {
let name: String
public let name: String
let primaryKey: String
let foreignKey: String
private var foreignIDsWithNoRelationship = Set<String>()
@ -32,6 +32,10 @@ public final class LookupTable {
self.foreignKey = foreignKey
}
public func fetchObjectsWithIDs(_ databaseIDs: Set<String>, _ database: FMDatabase) -> [DatabaseObject] {
}
public func fetchLookupTableDictionary(_ foreignIDs: Set<String>, _ database: FMDatabase) -> LookupTableDictionary? {
let foreignIDsToLookup = foreignIDs.subtracting(foreignIDsWithNoRelationship)
@ -64,28 +68,28 @@ public final class LookupTable {
return lookupTableDictionary(with: lookupValues)
}
public func attachRelationships<T,U>(to objects: [T], idKeyPath: KeyPath<T,String>, relatedIDKeyPath: KeyPath<U,String>, relationshipKeyPath: KeyPath<T,[U]>, table: DatabaseTable, lookupTableDictionary: LookupTableDictionary, database: FMDatabase) {
public func attachRelationships(to objects: [DatabaseObject], table: DatabaseTable, lookupTableDictionary: LookupTableDictionary, relationshipName: String, database: FMDatabase) {
let primaryIDs = primaryIDsInLookupTableDictionary(lookupTableDictionary)
if (primaryIDs.isEmpty) {
return
}
let relatedObjects: [U] = table.fetchObjectsWithIDs(primaryIDs, database)
let relatedObjects: [DatabaseObject] = table.fetchObjectsWithIDs(primaryIDs, database)
if relatedObjects.isEmpty {
return
}
let relatedObjectsDictionary = createRelatedObjectsDictionary(relatedObjects, idKeyPath: relatedIDKeyPath)
let relatedObjectsDictionary = relatedObjects.dictionary()
for object in objects {
let identifier = object[keyPath: idKeyPath]
let identifier = object.databaseID
if let lookupValues = lookupTableDictionary[identifier], !lookupValues.isEmpty {
let primaryIDs = lookupValues.primaryIDs()
let oneObjectRelatedObjects = primaryIDs.flatMap{ (primaryID) -> U? in
let oneObjectRelatedObjects = primaryIDs.flatMap{ (primaryID) -> DatabaseObject? in
return relatedObjectsDictionary[primaryID]
}
object[keyPath: relationshipKeyPath] = oneObjectRelatedObjects
object.attachRelationshipWithObjects(oneObjectRelatedObjects, name: relationshipName)
}
}
}
@ -119,18 +123,6 @@ public final class LookupTable {
private extension LookupTable {
func createRelatedObjectsDictionary<T>(_ relatedObjects: [T], idKeyPath: KeyPath<T,String>) -> [String: T] {
var d = [String: T]()
for object in relatedObjects {
let identifier = object[keyPath: idKeyPath]
d[identifier] = object
}
return d
}
func addToLookupTableDictionary(_ lookupValues: Set<LookupValue>, _ table: inout LookupTableDictionary) {
for lookupValue in lookupValues {
@ -174,16 +166,17 @@ private extension LookupTable {
return resultSet.mapToSet(lookupValueWithRow)
}
func lookupValueWithRow(_ resultSet: FMResultSet) -> LookupValue? {
func lookupValueWithRow(_ row: FMResultSet) -> LookupValue? {
guard let primaryID = resultSet.string(forColumn: primaryKey) else {
guard let primaryID = row.string(forColumn: primaryKey) else {
return nil
}
guard let foreignID = resultSet.string(forColumn: foreignKey) else {
guard let foreignID = row.string(forColumn: foreignKey) else {
return nil
}
return LookupValue(primaryID: primaryID, foreignID: foreignID)
}
}
public struct LookupValue: Hashable {