From 8569c3c524529ad4e8709fac26d3d924f535547a Mon Sep 17 00:00:00 2001 From: John Estropia Date: Wed, 1 Mar 2017 19:34:07 +0900 Subject: [PATCH] WIP: rehaul of type-safe fetching and querying --- CoreStore.xcodeproj/project.pbxproj | 28 +- .../BaseDataTransaction+Querying.swift | 4 +- .../Concrete Clauses/Select.swift | 713 +++++++++--------- .../CoreStore+Querying.swift | 4 +- .../CoreStoreQueryableAttributeType.swift | 226 +++++- .../DataStack+Querying.swift | 4 +- .../QueryableSource.swift | 4 +- .../CoreStoreImportableAttributeType.swift | 11 +- .../NSManagedObjectContext+Querying.swift | 34 +- 9 files changed, 638 insertions(+), 390 deletions(-) diff --git a/CoreStore.xcodeproj/project.pbxproj b/CoreStore.xcodeproj/project.pbxproj index 856048e..c373ac7 100644 --- a/CoreStore.xcodeproj/project.pbxproj +++ b/CoreStore.xcodeproj/project.pbxproj @@ -1038,6 +1038,13 @@ path = Migrating; sourceTree = ""; }; + B57358D71E5A7F9B0094B50A /* Dynamic Models */ = { + isa = PBXGroup; + children = ( + ); + path = "Dynamic Models"; + sourceTree = ""; + }; B5A5F26B1CAFF8D0004AB9AF /* Swift */ = { isa = PBXGroup; children = ( @@ -1114,7 +1121,7 @@ B5F1DA8C1B9AA97D007C5CBB /* ImportableObject.swift */, B5F1DA8F1B9AA991007C5CBB /* ImportableUniqueObject.swift */, B5E834B81B76311F001D3D50 /* BaseDataTransaction+Importing.swift */, - B509C7F31E54511B0061C547 /* CoreStoreUniqueIDAttributeType.swift */, + B509C7F31E54511B0061C547 /* CoreStoreImportableAttributeType.swift */, ); path = Importing; sourceTree = ""; @@ -1124,6 +1131,7 @@ children = ( B504D0D51B02362500B2BBB1 /* CoreStore+Setup.swift */, B5E84EDB1AFF84500064E85B /* DataStack.swift */, + B57358D71E5A7F9B0094B50A /* Dynamic Models */, B5FE4DA01C84818B00FA6A91 /* StorageInterfaces */, ); path = Setup; @@ -1164,7 +1172,7 @@ B5E84F071AFF847B0064E85B /* CoreStore+Querying.swift */, B596BBB51DD5BC67001DCDD9 /* FetchableSource.swift */, B596BBBA1DD5C39F001DCDD9 /* QueryableSource.swift */, - B549F65D1E569C7400FBAB2D /* CoreStoreQueryingAttributeType.swift */, + B549F65D1E569C7400FBAB2D /* CoreStoreQueryableAttributeType.swift */, B5E84F0A1AFF847B0064E85B /* Protocol Clauses */, B5E84EFF1AFF847B0064E85B /* Concrete Clauses */, ); @@ -1593,7 +1601,7 @@ B5E1B59D1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, B5ECDC231CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */, B549F6731E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, - B509C7F41E54511B0061C547 /* CoreStoreUniqueIDAttributeType.swift in Sources */, + B509C7F41E54511B0061C547 /* CoreStoreImportableAttributeType.swift in Sources */, B5E84F0E1AFF847B0064E85B /* Tweak.swift in Sources */, B5E1B5931CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5ECDC291CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, @@ -1665,7 +1673,7 @@ B5E84F301AFF849C0064E85B /* NSManagedObjectContext+CoreStore.swift in Sources */, B546F9691C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B53FBA1E1CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, - B549F65E1E569C7400FBAB2D /* CoreStoreQueryingAttributeType.swift in Sources */, + B549F65E1E569C7400FBAB2D /* CoreStoreQueryableAttributeType.swift in Sources */, B5E84F211AFF84860064E85B /* CoreStore+Observing.swift in Sources */, B559CD431CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B5FE4DA71C84FB4400FA6A91 /* InMemoryStore.swift in Sources */, @@ -1749,7 +1757,7 @@ B5E1B59F1CAA2568007FD580 /* CSDataStack+Observing.swift in Sources */, B5ECDC251CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */, B549F6741E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, - B509C7F51E54511B0061C547 /* CoreStoreUniqueIDAttributeType.swift in Sources */, + B509C7F51E54511B0061C547 /* CoreStoreImportableAttributeType.swift in Sources */, 82BA18B31C4BBD3900A0916E /* ImportableUniqueObject.swift in Sources */, B5E1B5951CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5ECDC2B1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, @@ -1821,7 +1829,7 @@ B546F96A1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B53FBA201CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, 82BA18A81C4BBD2900A0916E /* CoreStoreLogger.swift in Sources */, - B549F65F1E569C7400FBAB2D /* CoreStoreQueryingAttributeType.swift in Sources */, + B549F65F1E569C7400FBAB2D /* CoreStoreQueryableAttributeType.swift in Sources */, B559CD451CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, 82BA18B81C4BBD4200A0916E /* ClauseTypes.swift in Sources */, B5ECDBEE1CA6BF2000C7F112 /* CSFrom.swift in Sources */, @@ -1905,7 +1913,7 @@ B559CD471CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B5ECDBF01CA6BF2000C7F112 /* CSFrom.swift in Sources */, B549F6761E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, - B509C7F71E54511B0061C547 /* CoreStoreUniqueIDAttributeType.swift in Sources */, + B509C7F71E54511B0061C547 /* CoreStoreImportableAttributeType.swift in Sources */, B5220E1F1D130810009BC71E /* CSListObserver.swift in Sources */, B52DD1941BE1F92500949AFE /* CoreStore.swift in Sources */, B52DD1A61BE1F92F00949AFE /* BaseDataTransaction+Importing.swift in Sources */, @@ -1977,7 +1985,7 @@ B52DD1BB1BE1F94000949AFE /* MigrationType.swift in Sources */, B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */, B5220E151D130663009BC71E /* CoreStore+Observing.swift in Sources */, - B549F6611E569C7400FBAB2D /* CoreStoreQueryingAttributeType.swift in Sources */, + B549F6611E569C7400FBAB2D /* CoreStoreQueryableAttributeType.swift in Sources */, B52DD19B1BE1F92800949AFE /* CoreStoreLogger.swift in Sources */, B52DD1991BE1F92800949AFE /* DefaultLogger.swift in Sources */, B5220E201D130813009BC71E /* CSObjectMonitor.swift in Sources */, @@ -2061,7 +2069,7 @@ B5ECDC261CA81A3900C7F112 /* CSCoreStore+Querying.swift in Sources */, B563217F1BD65216006C9394 /* CoreStore.swift in Sources */, B549F6751E56A92800FBAB2D /* CoreDataNativeType.swift in Sources */, - B509C7F61E54511B0061C547 /* CoreStoreUniqueIDAttributeType.swift in Sources */, + B509C7F61E54511B0061C547 /* CoreStoreImportableAttributeType.swift in Sources */, B5E1B5961CAA0C15007FD580 /* CSObjectMonitor.swift in Sources */, B5ECDC2C1CA81CC700C7F112 /* CSDataStack+Transaction.swift in Sources */, B56321911BD65216006C9394 /* BaseDataTransaction+Importing.swift in Sources */, @@ -2133,7 +2141,7 @@ B546F96B1C9AF26D00D5AC55 /* CSInMemoryStore.swift in Sources */, B53FBA211CAB63FA00F0D40A /* NSFetchedResultsController+ObjectiveC.swift in Sources */, B563218B1BD65216006C9394 /* UnsafeDataTransaction.swift in Sources */, - B549F6601E569C7400FBAB2D /* CoreStoreQueryingAttributeType.swift in Sources */, + B549F6601E569C7400FBAB2D /* CoreStoreQueryableAttributeType.swift in Sources */, B559CD461CAA8B6300E4D58B /* CSSetupResult.swift in Sources */, B56321A61BD65216006C9394 /* MigrationType.swift in Sources */, B5ECDBEF1CA6BF2000C7F112 /* CSFrom.swift in Sources */, diff --git a/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift b/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift index 777bcd0..fc7835a 100644 --- a/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift +++ b/Sources/Fetching and Querying/BaseDataTransaction+Querying.swift @@ -287,7 +287,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { CoreStore.assert( self.isRunningInAllowedQueue(), @@ -306,7 +306,7 @@ extension BaseDataTransaction: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { CoreStore.assert( self.isRunningInAllowedQueue(), diff --git a/Sources/Fetching and Querying/Concrete Clauses/Select.swift b/Sources/Fetching and Querying/Concrete Clauses/Select.swift index 89f7a9b..fb2bd33 100644 --- a/Sources/Fetching and Querying/Concrete Clauses/Select.swift +++ b/Sources/Fetching and Querying/Concrete Clauses/Select.swift @@ -32,31 +32,34 @@ import CoreData /** The `SelectResultType` protocol is implemented by return types supported by the `Select` clause. */ -public protocol SelectResultType {} +public protocol SelectResultType: CoreStoreQueryableAttributeType { - -// MARK: - SelectValueResultType - -/** - The `SelectValueResultType` protocol is implemented by return types supported by the `queryValue(...)` methods. - */ -public protocol SelectValueResultType: SelectResultType { - static var attributeType: NSAttributeType { get } - - static func fromResultObject(_ result: Any) -> Self? } -// MARK: - SelectAttributesResultType +//// MARK: - SelectValueResultType +// +///** +// The `SelectValueResultType` protocol is implemented by return types supported by the `queryValue(...)` methods. +// */ +//public protocol SelectValueResultType: SelectResultType { +// +// static var attributeType: NSAttributeType { get } +// +// static func fromResultObject(_ result: Any) -> Self? +//} -/** - The `SelectValueResultType` protocol is implemented by return types supported by the `queryAttributes(...)` methods. - */ -public protocol SelectAttributesResultType: SelectResultType { - - static func fromResultObjects(_ result: [Any]) -> [[String: Any]] -} + +//// MARK: - SelectAttributesResultType +// +///** +// The `SelectValueResultType` protocol is implemented by return types supported by the `queryAttributes(...)` methods. +// */ +//public protocol SelectAttributesResultType: SelectResultType { +// +// static func fromResultObjects(_ result: [Any]) -> [[String: Any]] +//} // MARK: - SelectTerm @@ -335,7 +338,7 @@ public enum SelectTerm: ExpressibleByStringLiteral, Hashable { - parameter sortDescriptors: a series of `NSSortDescriptor`s */ -public struct Select: Hashable { +public struct Select: Hashable { /** The `SelectResultType` type for the query's return value @@ -366,7 +369,7 @@ public struct Select: Hashable { // MARK: Equatable - public static func == (lhs: Select, rhs: Select) -> Bool { + public static func == (lhs: Select, rhs: Select) -> Bool { return lhs.selectTerms == rhs.selectTerms } @@ -394,340 +397,340 @@ public extension Select where T: NSManagedObjectID { } -// MARK: - Bool: SelectValueResultType - -extension Bool: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .booleanAttributeType - } - - public static func fromResultObject(_ result: Any) -> Bool? { - switch result { - - case let decimal as NSDecimalNumber: - // iOS: NSDecimalNumber(string: "0.5").boolValue // true - // OSX: NSDecimalNumber(string: "0.5").boolValue // false - return NSNumber(value: decimal.doubleValue).boolValue - - case let number as NSNumber: - return number.boolValue - - default: - return nil - } - } -} - - -// MARK: - Int8: SelectValueResultType - -extension Int8: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public static func fromResultObject(_ result: Any) -> Int8? { - - guard let value = (result as? NSNumber)?.int64Value else { - - return nil - } - return numericCast(value) as Int8 - } -} - - -// MARK: - Int16: SelectValueResultType - -extension Int16: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public static func fromResultObject(_ result: Any) -> Int16? { - - guard let value = (result as? NSNumber)?.int64Value else { - - return nil - } - return numericCast(value) as Int16 - } -} - - -// MARK: - Int32: SelectValueResultType - -extension Int32: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public static func fromResultObject(_ result: Any) -> Int32? { - - guard let value = (result as? NSNumber)?.int64Value else { - - return nil - } - return numericCast(value) as Int32 - } -} - - -// MARK: - Int64: SelectValueResultType - -extension Int64: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public static func fromResultObject(_ result: Any) -> Int64? { - - return (result as? NSNumber)?.int64Value - } -} - - -// MARK: - Int: SelectValueResultType - -extension Int: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public static func fromResultObject(_ result: Any) -> Int? { - - guard let value = (result as? NSNumber)?.int64Value else { - - return nil - } - return numericCast(value) as Int - } -} - - -// MARK: - Double : SelectValueResultType - -extension Double: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .doubleAttributeType - } - - public static func fromResultObject(_ result: Any) -> Double? { - - return (result as? NSNumber)?.doubleValue - } -} - - -// MARK: - Float: SelectValueResultType - -extension Float: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .floatAttributeType - } - - public static func fromResultObject(_ result: Any) -> Float? { - - return (result as? NSNumber)?.floatValue - } -} - - -// MARK: - String: SelectValueResultType - -extension String: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .stringAttributeType - } - - public static func fromResultObject(_ result: Any) -> String? { - - return result as? String - } -} - - -// MARK: - Date: SelectValueResultType - -extension Date: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .dateAttributeType - } - - public static func fromResultObject(_ result: Any) -> Date? { - - return result as? Date - } -} - - -// MARK: - Data: SelectValueResultType - -extension Data: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .binaryDataAttributeType - } - - public static func fromResultObject(_ result: Any) -> Data? { - - return result as? Data - } -} - - -// MARK: - NSNumber: SelectValueResultType - -extension NSNumber: SelectValueResultType { - - public class var attributeType: NSAttributeType { - - return .integer64AttributeType - } - - public class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSString: SelectValueResultType - -extension NSString: SelectValueResultType { - - public class var attributeType: NSAttributeType { - - return .stringAttributeType - } - - public class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSDecimalNumber: SelectValueResultType - -extension NSDecimalNumber { - - public override class var attributeType: NSAttributeType { - - return .decimalAttributeType - } - - public override class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSDate: SelectValueResultType - -extension NSDate: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .dateAttributeType - } - - public class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSData: SelectValueResultType - -extension NSData: SelectValueResultType { - - public static var attributeType: NSAttributeType { - - return .binaryDataAttributeType - } - - public class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSManagedObjectID: SelectValueResultType - -extension NSManagedObjectID: SelectValueResultType { - - public class var attributeType: NSAttributeType { - - return .objectIDAttributeType - } - - public class func fromResultObject(_ result: Any) -> Self? { - - func forceCast(_ object: Any) -> T? { - - return (object as? T) - } - return forceCast(result) - } -} - - -// MARK: - NSManagedObjectID: SelectAttributesResultType - -extension NSDictionary: SelectAttributesResultType { - - // MARK: SelectAttributesResultType - - public class func fromResultObjects(_ result: [Any]) -> [[String: Any]] { - - return result as! [[String: Any]] - } -} +//// MARK: - Bool: SelectValueResultType +// +//extension Bool: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .booleanAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Bool? { +// switch result { +// +// case let decimal as NSDecimalNumber: +// // iOS: NSDecimalNumber(string: "0.5").boolValue // true +// // OSX: NSDecimalNumber(string: "0.5").boolValue // false +// return NSNumber(value: decimal.doubleValue).boolValue +// +// case let number as NSNumber: +// return number.boolValue +// +// default: +// return nil +// } +// } +//} +// +// +//// MARK: - Int8: SelectValueResultType +// +//extension Int8: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Int8? { +// +// guard let value = (result as? NSNumber)?.int64Value else { +// +// return nil +// } +// return numericCast(value) as Int8 +// } +//} +// +// +//// MARK: - Int16: SelectValueResultType +// +//extension Int16: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Int16? { +// +// guard let value = (result as? NSNumber)?.int64Value else { +// +// return nil +// } +// return numericCast(value) as Int16 +// } +//} +// +// +//// MARK: - Int32: SelectValueResultType +// +//extension Int32: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Int32? { +// +// guard let value = (result as? NSNumber)?.int64Value else { +// +// return nil +// } +// return numericCast(value) as Int32 +// } +//} +// +// +//// MARK: - Int64: SelectValueResultType +// +//extension Int64: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Int64? { +// +// return (result as? NSNumber)?.int64Value +// } +//} +// +// +//// MARK: - Int: SelectValueResultType +// +//extension Int: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Int? { +// +// guard let value = (result as? NSNumber)?.int64Value else { +// +// return nil +// } +// return numericCast(value) as Int +// } +//} +// +// +//// MARK: - Double : SelectValueResultType +// +//extension Double: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .doubleAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Double? { +// +// return (result as? NSNumber)?.doubleValue +// } +//} +// +// +//// MARK: - Float: SelectValueResultType +// +//extension Float: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .floatAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Float? { +// +// return (result as? NSNumber)?.floatValue +// } +//} +// +// +//// MARK: - String: SelectValueResultType +// +//extension String: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .stringAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> String? { +// +// return result as? String +// } +//} +// +// +//// MARK: - Date: SelectValueResultType +// +//extension Date: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .dateAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Date? { +// +// return result as? Date +// } +//} +// +// +//// MARK: - Data: SelectValueResultType +// +//extension Data: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .binaryDataAttributeType +// } +// +// public static func fromResultObject(_ result: Any) -> Data? { +// +// return result as? Data +// } +//} +// +// +//// MARK: - NSNumber: SelectValueResultType +// +//extension NSNumber: SelectValueResultType { +// +// public class var attributeType: NSAttributeType { +// +// return .integer64AttributeType +// } +// +// public class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSString: SelectValueResultType +// +//extension NSString: SelectValueResultType { +// +// public class var attributeType: NSAttributeType { +// +// return .stringAttributeType +// } +// +// public class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSDecimalNumber: SelectValueResultType +// +//extension NSDecimalNumber { +// +// public override class var attributeType: NSAttributeType { +// +// return .decimalAttributeType +// } +// +// public override class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSDate: SelectValueResultType +// +//extension NSDate: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .dateAttributeType +// } +// +// public class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSData: SelectValueResultType +// +//extension NSData: SelectValueResultType { +// +// public static var attributeType: NSAttributeType { +// +// return .binaryDataAttributeType +// } +// +// public class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSManagedObjectID: SelectValueResultType +// +//extension NSManagedObjectID: SelectValueResultType { +// +// public class var attributeType: NSAttributeType { +// +// return .objectIDAttributeType +// } +// +// public class func fromResultObject(_ result: Any) -> Self? { +// +// func forceCast(_ object: Any) -> T? { +// +// return (object as? T) +// } +// return forceCast(result) +// } +//} +// +// +//// MARK: - NSManagedObjectID: SelectAttributesResultType +// +//extension NSDictionary: SelectAttributesResultType { +// +// // MARK: SelectAttributesResultType +// +// public class func fromResultObjects(_ result: [Any]) -> [[String: Any]] { +// +// return result as! [[String: Any]] +// } +//} // MARK: - Internal diff --git a/Sources/Fetching and Querying/CoreStore+Querying.swift b/Sources/Fetching and Querying/CoreStore+Querying.swift index 18ff1d0..12a31eb 100644 --- a/Sources/Fetching and Querying/CoreStore+Querying.swift +++ b/Sources/Fetching and Querying/CoreStore+Querying.swift @@ -205,7 +205,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { return self.defaultStack.queryValue(from, selectClause, queryClauses) } @@ -220,7 +220,7 @@ public extension CoreStore { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public static func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { return self.defaultStack.queryValue(from, selectClause, queryClauses) } diff --git a/Sources/Fetching and Querying/CoreStoreQueryableAttributeType.swift b/Sources/Fetching and Querying/CoreStoreQueryableAttributeType.swift index b0a63dd..1b8d0f7 100644 --- a/Sources/Fetching and Querying/CoreStoreQueryableAttributeType.swift +++ b/Sources/Fetching and Querying/CoreStoreQueryableAttributeType.swift @@ -34,21 +34,30 @@ public protocol CoreStoreQueryableAttributeType: Hashable { associatedtype QueryableNativeType: CoreDataNativeType + static var cs_rawAttributeType: NSAttributeType { get } + + @inline(__always) + static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? + + @inline(__always) func cs_toQueryableNativeType() -> QueryableNativeType } -// MARK: - NSManagedObject - -extension NSManagedObject: CoreStoreQueryableAttributeType { - - public typealias QueryableNativeType = NSManagedObjectID - - public func cs_toQueryableNativeType() -> QueryableNativeType { - - return self.objectID - } -} +//// MARK: - NSManagedObject +// +//extension NSManagedObject: CoreStoreQueryableAttributeType { +// +// public typealias QueryableNativeType = NSManagedObjectID +// +// public static let cs_rawAttributeType: NSAttributeType = .objectIDAttributeType +// +// @inline(__always) +// public func cs_toQueryableNativeType() -> QueryableNativeType { +// +// return self.objectID +// } +//} // MARK: - NSManagedObjectID @@ -57,6 +66,19 @@ extension NSManagedObjectID: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSManagedObjectID + public static let cs_rawAttributeType: NSAttributeType = .objectIDAttributeType + + @nonobjc @inline(__always) + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self @@ -70,6 +92,21 @@ extension NSNumber: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public class var cs_rawAttributeType: NSAttributeType { + + return .integer64AttributeType + } + + @nonobjc @inline(__always) + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) + } + public func cs_toQueryableNativeType() -> QueryableNativeType { return self @@ -77,12 +114,36 @@ extension NSNumber: CoreStoreQueryableAttributeType { } +// MARK: - NSNumber + +extension NSDecimalNumber /*: CoreStoreQueryableAttributeType */ { + + public override class var cs_rawAttributeType: NSAttributeType { + + return .decimalAttributeType + } +} + + // MARK: - NSString extension NSString: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSString + public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType + + @nonobjc @inline(__always) + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self @@ -96,6 +157,19 @@ extension NSDate: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSDate + public static let cs_rawAttributeType: NSAttributeType = .dateAttributeType + + @nonobjc @inline(__always) + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self @@ -109,6 +183,19 @@ extension NSData: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSData + public static let cs_rawAttributeType: NSAttributeType = .binaryDataAttributeType + + @nonobjc @inline(__always) + public class func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + func forceCast(_ value: Any) -> T? { + + return value as? T + } + return forceCast(value) + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self @@ -122,6 +209,24 @@ extension Bool: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .booleanAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Bool? { + + switch value { + + case let decimal as NSDecimalNumber: + // iOS: NSDecimalNumber(string: "0.5").boolValue // true + // OSX: NSDecimalNumber(string: "0.5").boolValue // false + return NSNumber(value: decimal.doubleValue).boolValue + + default: + return value.boolValue + } + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -135,6 +240,15 @@ extension Int16: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .integer16AttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Int16? { + + return value.int16Value + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -148,6 +262,15 @@ extension Int32: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .integer32AttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Int32? { + + return value.int32Value + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -161,6 +284,15 @@ extension Int64: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .integer64AttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Int64? { + + return value.int64Value + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -174,6 +306,15 @@ extension Int: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .integer64AttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Int? { + + return value.intValue + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -187,6 +328,15 @@ extension Double: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .doubleAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Double? { + + return value.doubleValue + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -200,6 +350,15 @@ extension Float: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .floatAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Float? { + + return value.floatValue + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -213,6 +372,15 @@ extension CGFloat: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNumber + public static let cs_rawAttributeType: NSAttributeType = .doubleAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> CGFloat? { + + return CGFloat(value.doubleValue) + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSNumber @@ -226,6 +394,15 @@ extension Date: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSDate + public static let cs_rawAttributeType: NSAttributeType = .dateAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Date? { + + return value as Date + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSDate @@ -239,6 +416,15 @@ extension String: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSString + public static let cs_rawAttributeType: NSAttributeType = .stringAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> String? { + + return value as String + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSString @@ -252,6 +438,15 @@ extension Data: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSData + public static let cs_rawAttributeType: NSAttributeType = .binaryDataAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Data? { + + return value as Data + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self as NSData @@ -265,6 +460,15 @@ extension NSNull: CoreStoreQueryableAttributeType { public typealias QueryableNativeType = NSNull + public static let cs_rawAttributeType: NSAttributeType = .undefinedAttributeType + + @inline(__always) + public static func cs_fromQueryableNativeType(_ value: QueryableNativeType) -> Self? { + + return self.init() + } + + @inline(__always) public func cs_toQueryableNativeType() -> QueryableNativeType { return self diff --git a/Sources/Fetching and Querying/DataStack+Querying.swift b/Sources/Fetching and Querying/DataStack+Querying.swift index d9a771a..dfca7f8 100644 --- a/Sources/Fetching and Querying/DataStack+Querying.swift +++ b/Sources/Fetching and Querying/DataStack+Querying.swift @@ -250,7 +250,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { CoreStore.assert( Thread.isMainThread, @@ -269,7 +269,7 @@ extension DataStack: FetchableSource, QueryableSource { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { CoreStore.assert( Thread.isMainThread, diff --git a/Sources/Fetching and Querying/QueryableSource.swift b/Sources/Fetching and Querying/QueryableSource.swift index 0c9529e..531df53 100644 --- a/Sources/Fetching and Querying/QueryableSource.swift +++ b/Sources/Fetching and Querying/QueryableSource.swift @@ -44,7 +44,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? + func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? /** Queries aggregate values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. @@ -56,7 +56,7 @@ public protocol QueryableSource: class { - parameter queryClauses: a series of `QueryClause` instances for the query request. Accepts `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. - returns: the result of the the query. The type of the return value is specified by the generic type of the `Select` parameter. */ - func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? + func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? /** Queries a dictionary of attribute values as specified by the `QueryClause`s. Requires at least a `Select` clause, and optional `Where`, `OrderBy`, `GroupBy`, and `Tweak` clauses. diff --git a/Sources/Importing/CoreStoreImportableAttributeType.swift b/Sources/Importing/CoreStoreImportableAttributeType.swift index 8e14e9c..790012d 100644 --- a/Sources/Importing/CoreStoreImportableAttributeType.swift +++ b/Sources/Importing/CoreStoreImportableAttributeType.swift @@ -152,7 +152,16 @@ extension Bool: CoreStoreImportableAttributeType { @inline(__always) public static func cs_fromImportableNativeType(_ value: ImportableNativeType) -> Bool? { - return value.boolValue + switch value { + + case let decimal as NSDecimalNumber: + // iOS: NSDecimalNumber(string: "0.5").boolValue // true + // OSX: NSDecimalNumber(string: "0.5").boolValue // false + return NSNumber(value: decimal.doubleValue).boolValue + + default: + return value.boolValue + } } } diff --git a/Sources/Internal/NSManagedObjectContext+Querying.swift b/Sources/Internal/NSManagedObjectContext+Querying.swift index bb44498..181507f 100644 --- a/Sources/Internal/NSManagedObjectContext+Querying.swift +++ b/Sources/Internal/NSManagedObjectContext+Querying.swift @@ -238,13 +238,13 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { // MARK: QueryableSource @nonobjc - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> U? { return self.queryValue(from, selectClause, queryClauses) } @nonobjc - public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { + public func queryValue(_ from: From, _ selectClause: Select, _ queryClauses: [QueryClause]) -> U? { let fetchRequest = CoreStoreFetchRequest() let storeFound = from.applyToFetchRequest(fetchRequest, context: self) @@ -262,6 +262,30 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.queryValue(selectTerms, fetchRequest: fetchRequest) } + @nonobjc + public func queryAttributes(_ from: From, _ selectClause: Select<[U]>, _ queryClauses: QueryClause...) -> [[String: Any]]? { + + return self.queryAttributes(from, selectClause, queryClauses) + } + + @nonobjc + public func queryAttributes(_ from: From, _ selectClause: Select<[U]>, _ queryClauses: [QueryClause]) -> [[String: Any]]? { + + let fetchRequest = CoreStoreFetchRequest() + let storeFound = from.applyToFetchRequest(fetchRequest, context: self) + + fetchRequest.fetchLimit = 0 + + selectClause.selectTerms.applyToFetchRequest(fetchRequest, owner: selectClause) + queryClauses.forEach { $0.applyToFetchRequest(fetchRequest) } + + guard storeFound else { + + return nil + } + return self.queryAttributes(fetchRequest) + } + @nonobjc public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { @@ -415,7 +439,7 @@ internal extension NSManagedObjectContext { // MARK: Querying @nonobjc - internal func queryValue(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> U? { + internal func queryValue(_ selectTerms: [SelectTerm], fetchRequest: NSFetchRequest) -> U? { var fetchResults: [Any]? var fetchError: Error? @@ -433,9 +457,9 @@ internal extension NSManagedObjectContext { if let fetchResults = fetchResults { if let rawResult = fetchResults.first as? NSDictionary, - let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] { + let rawObject = rawResult[selectTerms.keyPathForFirstSelectTerm()] as? U.QueryableNativeType { - return Select.ReturnType.fromResultObject(rawObject) + return U.cs_fromQueryableNativeType(rawObject) } return nil }