diff --git a/CoreStoreTests/GroupByTests.swift b/CoreStoreTests/GroupByTests.swift index cf1e583..5f57f26 100644 --- a/CoreStoreTests/GroupByTests.swift +++ b/CoreStoreTests/GroupByTests.swift @@ -38,14 +38,14 @@ final class GroupByTests: BaseTestCase { do { - let groupBy = GroupBy() + let groupBy = GroupBy() XCTAssertEqual(groupBy, GroupBy([] as [String])) XCTAssertNotEqual(groupBy, GroupBy("key")) XCTAssertTrue(groupBy.keyPaths.isEmpty) } do { - let groupBy = GroupBy("key1") + let groupBy = GroupBy("key1") XCTAssertEqual(groupBy, GroupBy("key1")) XCTAssertEqual(groupBy, GroupBy(["key1"])) XCTAssertNotEqual(groupBy, GroupBy("key2")) @@ -53,7 +53,7 @@ final class GroupByTests: BaseTestCase { } do { - let groupBy = GroupBy("key1", "key2") + let groupBy = GroupBy("key1", "key2") XCTAssertEqual(groupBy, GroupBy("key1", "key2")) XCTAssertEqual(groupBy, GroupBy(["key1", "key2"])) XCTAssertNotEqual(groupBy, GroupBy("key2", "key1")) @@ -66,7 +66,7 @@ final class GroupByTests: BaseTestCase { self.prepareStack { (dataStack) in - let groupBy = GroupBy(#keyPath(TestEntity1.testString)) + let groupBy = GroupBy(#keyPath(TestEntity1.testString)) let request = CoreStoreFetchRequest() _ = From().applyToFetchRequest(request, context: dataStack.mainContext) diff --git a/CoreStoreTests/WhereTests.swift b/CoreStoreTests/WhereTests.swift index 4722b37..af9d9f0 100644 --- a/CoreStoreTests/WhereTests.swift +++ b/CoreStoreTests/WhereTests.swift @@ -31,12 +31,12 @@ import CoreStore // MARK: - XCTAssertAllEqual -private func XCTAssertAllEqual(_ whereClauses: Where...) { +private func XCTAssertAllEqual(_ whereClauses: Where...) { XCTAssertAllEqual(whereClauses) } -private func XCTAssertAllEqual(_ whereClauses: [Where]) { +private func XCTAssertAllEqual(_ whereClauses: [Where]) { for i in whereClauses.indices { diff --git a/Sources/AttributeProtocol.swift b/Sources/AttributeProtocol.swift index 9d6c017..4bc91bb 100644 --- a/Sources/AttributeProtocol.swift +++ b/Sources/AttributeProtocol.swift @@ -33,7 +33,7 @@ internal protocol AttributeProtocol: class { static var attributeType: NSAttributeType { get } - var keyPath: RawKeyPath { get } + var keyPath: KeyPathString { get } var isOptional: Bool { get } var isIndexed: Bool { get } var isTransient: Bool { get } diff --git a/Sources/CSGroupBy.swift b/Sources/CSGroupBy.swift index 9f79679..f5f97c2 100644 --- a/Sources/CSGroupBy.swift +++ b/Sources/CSGroupBy.swift @@ -35,7 +35,7 @@ import CoreData - SeeAlso: `GroupBy` */ @objc -public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { +public final class CSGroupBy: NSObject, CSQueryClause { /** The list of key path strings to group results with @@ -102,11 +102,11 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { // MARK: CoreStoreObjectiveCType - public let bridgeToSwift: GroupBy + public let bridgeToSwift: GroupBy - public init(_ swiftValue: GroupBy) { + public init(_ swiftValue: GroupBy) { - self.bridgeToSwift = swiftValue + self.bridgeToSwift = swiftValue.downcast() super.init() } } @@ -114,7 +114,7 @@ public final class CSGroupBy: NSObject, CSQueryClause, CoreStoreObjectiveCType { // MARK: - GroupBy -extension GroupBy: CoreStoreSwiftType { +extension GroupBy where D: NSManagedObject { // MARK: CoreStoreSwiftType @@ -122,4 +122,12 @@ extension GroupBy: CoreStoreSwiftType { return CSGroupBy(self) } + + + // MARK: FilePrivate + + fileprivate func downcast() -> GroupBy { + + return GroupBy(self.keyPaths) + } } diff --git a/Sources/ChainedClauseBuilder.swift b/Sources/ChainedClauseBuilder.swift index 24f0584..432cdbb 100644 --- a/Sources/ChainedClauseBuilder.swift +++ b/Sources/ChainedClauseBuilder.swift @@ -42,7 +42,6 @@ public protocol QueryChainableBuilderType { var from: From { get set } var select: Select { get set } - var groupBy: GroupBy { get set } var queryClauses: [QueryClause] { get set } } @@ -80,7 +79,6 @@ public struct QueryChainBuilder: QueryCha public var from: From public var select: Select - public var groupBy: GroupBy public var queryClauses: [QueryClause] = [] } @@ -111,7 +109,6 @@ public extension From { return .init( from: self, select: .init(selectTerms), - groupBy: .init(), queryClauses: [] ) } @@ -215,19 +212,19 @@ public extension FetchChainBuilder { public extension QueryChainBuilder { + public func groupBy(_ clause: GroupBy) -> QueryChainBuilder { + + return self.queryChain(appending: clause) + } + public func groupBy(_ keyPath: KeyPathString, _ keyPaths: KeyPathString...) -> QueryChainBuilder { - return self.groupBy([keyPath] + keyPaths) + return self.groupBy(GroupBy([keyPath] + keyPaths)) } public func groupBy(_ keyPaths: [KeyPathString]) -> QueryChainBuilder { - return .init( - from: self.from, - select: self.select, - groupBy: .init(keyPaths), - queryClauses: self.queryClauses - ) + return self.queryChain(appending: GroupBy(keyPaths)) } public func `where`(_ clause: Where) -> QueryChainBuilder { @@ -268,7 +265,6 @@ public extension QueryChainBuilder { return .init( from: self.from, select: self.select, - groupBy: self.groupBy, queryClauses: self.queryClauses + [clause] ) } diff --git a/Sources/CoreStoreObject+Querying.swift b/Sources/CoreStoreObject+Querying.swift index 5f8c1ef..c0f9566 100644 --- a/Sources/CoreStoreObject+Querying.swift +++ b/Sources/CoreStoreObject+Querying.swift @@ -26,58 +26,6 @@ import CoreData import Foundation -//public extension From where D: NSManagedObject { -// -//// public func select(_ resultType: R.Type, _ selectTerm: SelectTerm, _ selectTerms: SelectTerm...) -> QueryChainBuilder { -//// -//// return self.select(resultType, [selectTerm] + selectTerms) -//// } -//// -//// public func select(_ resultType: R.Type, _ selectTerms: [SelectTerm]) -> QueryChainBuilder { -//// -//// return .init( -//// from: self, -//// select: .init(selectTerms), -//// groupBy: .init(), -//// fetchClauses: [] -//// ) -//// } -// -// public func sectionBy(_ sectionKeyPath: KeyPath) -> SectionMonitorChainBuilder { -// -// return self.sectionBy(sectionKeyPath._kvcKeyPathString!, { $0 }) -// } -// -// public func sectionBy(_ sectionKeyPath: KeyPath, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> SectionMonitorChainBuilder { -// -// return self.sectionBy(sectionKeyPath._kvcKeyPathString!, sectionIndexTransformer) -// } -// -// public func `where`(_ keyPath: KeyPath, isEqualTo value: Void?) -> FetchChainBuilder { -// -// return self.where(keyPath._kvcKeyPathString!, isEqualTo: value) -// } -// -// public func `where`(_ keyPath: KeyPath, isEqualTo value: U?) -> FetchChainBuilder { -// -// return self.where(keyPath._kvcKeyPathString!, isEqualTo: value) -// } -// -// public func `where`(_ keyPath: KeyPath, isEqualTo object: D?) -> FetchChainBuilder { -// -// return self.where(keyPath._kvcKeyPathString!, isEqualTo: object) -// } -// -// public func `where`(_ keyPath: KeyPath, isMemberOf list: S) -> FetchChainBuilder where S.Iterator.Element: QueryableAttributeType { -// -// return self.where(keyPath._kvcKeyPathString!, isMemberOf: list) -// } -// -// public func `where`(_ keyPath: KeyPath, isMemberOf list: S) -> FetchChainBuilder where S.Iterator.Element == D { -// -// return self.where(keyPath._kvcKeyPathString!, isMemberOf: list) -// } -//} // MARK: - DynamicObject diff --git a/Sources/DataStack+Querying.swift b/Sources/DataStack+Querying.swift index a0f527c..5f09687 100644 --- a/Sources/DataStack+Querying.swift +++ b/Sources/DataStack+Querying.swift @@ -153,7 +153,7 @@ extension DataStack: FetchableSource, QueryableSource { // TODO: docs public func fetchAll(_ clauseChain: B) -> [B.ObjectType]? { - + CoreStore.assert( Thread.isMainThread, "Attempted to fetch from a \(cs_typeName(self)) outside the main thread." diff --git a/Sources/GroupBy.swift b/Sources/GroupBy.swift index 0c6153f..1ee748b 100644 --- a/Sources/GroupBy.swift +++ b/Sources/GroupBy.swift @@ -32,12 +32,7 @@ import CoreData /** The `GroupBy` clause specifies that the result of a query be grouped accoording to the specified key path. */ -public struct GroupBy: QueryClause, Hashable { - - /** - The list of key path strings to group results with - */ - public let keyPaths: [KeyPathString] +public struct GroupBy: GroupByClause, QueryClause, Hashable { /** Initializes a `GroupBy` clause with an empty list of key path strings @@ -69,6 +64,13 @@ public struct GroupBy: QueryClause, Hashable { } + // MARK: WhereClause + + public typealias ObjectType = D + + public let keyPaths: [KeyPathString] + + // MARK: QueryClause public func applyToFetchRequest(_ fetchRequest: NSFetchRequest) { @@ -100,3 +102,22 @@ public struct GroupBy: QueryClause, Hashable { return (self.keyPaths as NSArray).hashValue } } + + +// MARK: - GroupByClause + +/** + Abstracts the `GroupBy` clause for protocol utilities. + */ +public protocol GroupByClause { + + /** + The `DynamicObject` type associated with the clause + */ + associatedtype ObjectType: DynamicObject + + /** + The list of key path strings to group results with + */ + var keyPaths: [KeyPathString] { get } +} diff --git a/Sources/NSManagedObjectContext+Querying.swift b/Sources/NSManagedObjectContext+Querying.swift index c9a2d31..a48304e 100644 --- a/Sources/NSManagedObjectContext+Querying.swift +++ b/Sources/NSManagedObjectContext+Querying.swift @@ -303,6 +303,12 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.queryValue(selectTerms, fetchRequest: fetchRequest) } + @nonobjc + public func queryValue(_ clauseChain: B) -> B.ResultType? where B : QueryChainableBuilderType, B.ResultType : QueryableAttributeType { + + return self.queryValue(clauseChain.from, clauseChain.select, clauseChain.queryClauses) + } + @nonobjc public func queryAttributes(_ from: From, _ selectClause: Select, _ queryClauses: QueryClause...) -> [[String: Any]]? { @@ -327,6 +333,11 @@ extension NSManagedObjectContext: FetchableSource, QueryableSource { return self.queryAttributes(fetchRequest) } + public func queryAttributes(_ clauseChain: B) -> [[String : Any]]? where B : QueryChainableBuilderType, B.ResultType == NSDictionary { + + return self.queryAttributes(clauseChain.from, clauseChain.select, clauseChain.queryClauses) + } + // MARK: FetchableSource, QueryableSource diff --git a/Sources/RelationshipProtocol.swift b/Sources/RelationshipProtocol.swift index de1ff88..aa401ea 100644 --- a/Sources/RelationshipProtocol.swift +++ b/Sources/RelationshipProtocol.swift @@ -31,11 +31,11 @@ import CoreData internal protocol RelationshipProtocol: class { - var keyPath: RawKeyPath { get } + var keyPath: KeyPathString { get } var isToMany: Bool { get } var isOrdered: Bool { get } var deleteRule: NSDeleteRule { get } - var inverse: (type: CoreStoreObject.Type, keyPath: () -> RawKeyPath?) { get } + var inverse: (type: CoreStoreObject.Type, keyPath: () -> KeyPathString?) { get } var affectedByKeyPaths: () -> Set { get } weak var parentObject: CoreStoreObject? { get set } var versionHashModifier: () -> String? { get } diff --git a/Sources/Transformable.swift b/Sources/Transformable.swift index 167cc78..435692f 100644 --- a/Sources/Transformable.swift +++ b/Sources/Transformable.swift @@ -116,7 +116,7 @@ public enum TransformableContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: RawKeyPath, + _ keyPath: KeyPathString, initial: @autoclosure @escaping () -> V, isIndexed: Bool = false, isTransient: Bool = false, @@ -197,7 +197,7 @@ public enum TransformableContainer { return .transformableAttributeType } - public let keyPath: RawKeyPath + public let keyPath: KeyPathString internal let isOptional = false internal let isIndexed: Bool @@ -261,7 +261,7 @@ public enum TransformableContainer { @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") public convenience init( - _ keyPath: RawKeyPath, + _ keyPath: KeyPathString, `default`: @autoclosure @escaping () -> V, isIndexed: Bool = false, isTransient: Bool = false, @@ -339,7 +339,7 @@ public enum TransformableContainer { - parameter affectedByKeyPaths: a set of key paths for properties whose values affect the value of the receiver. This is similar to `NSManagedObject.keyPathsForValuesAffectingValue(forKey:)`. */ public init( - _ keyPath: RawKeyPath, + _ keyPath: KeyPathString, initial: @autoclosure @escaping () -> V? = nil, isIndexed: Bool = false, isTransient: Bool = false, @@ -420,7 +420,7 @@ public enum TransformableContainer { return .transformableAttributeType } - public let keyPath: RawKeyPath + public let keyPath: KeyPathString internal let isOptional = true internal let isIndexed: Bool @@ -484,7 +484,7 @@ public enum TransformableContainer { @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") public convenience init( - _ keyPath: RawKeyPath, + _ keyPath: KeyPathString, `default`: @autoclosure @escaping () -> V? = nil, isIndexed: Bool = false, isTransient: Bool = false, diff --git a/Sources/Value.swift b/Sources/Value.swift index 72296fb..5f0c0b8 100644 --- a/Sources/Value.swift +++ b/Sources/Value.swift @@ -258,7 +258,7 @@ public enum ValueContainer { @available(*, deprecated: 3.2, renamed: "init(_:initial:isIndexed:isTransient:versionHashModifier:renamingIdentifier:customGetter:customSetter:affectedByKeyPaths:)") public convenience init( - _ keyPath: RawKeyPath, + _ keyPath: KeyPathString, `default`: @autoclosure @escaping () -> V, isIndexed: Bool = false, isTransient: Bool = false, diff --git a/Sources/Where+NSManagedObject.swift b/Sources/Where+NSManagedObject.swift index ef73499..ff0234b 100644 --- a/Sources/Where+NSManagedObject.swift +++ b/Sources/Where+NSManagedObject.swift @@ -29,192 +29,303 @@ import Foundation // MARK: - KeyPath where Root: NSManagedObject, Value: QueryableAttributeType & Equatable -public extension KeyPath where Root: NSManagedObject, Value: QueryableAttributeType & Equatable { +public func == (_ keyPath: KeyPath, _ value: V) -> Where { - public static func == (_ keyPath: KeyPath, _ value: Value) -> Where { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: value) - } - - public static func != (_ keyPath: KeyPath, _ value: Value) -> Where { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: value) - } - - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == Value { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) - } + return Where(keyPath._kvcKeyPathString!, isEqualTo: value) } +public func != (_ keyPath: KeyPath, _ value: V) -> Where { + + return !Where(keyPath._kvcKeyPathString!, isEqualTo: value) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == V { + + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) +} + + // MARK: - KeyPath where Root: NSManagedObject, Value: Optional -public extension KeyPath where Root: NSManagedObject { +public func == (_ keyPath: KeyPath>, _ value: V?) -> Where { - public static func == (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: value) - } + return Where(keyPath._kvcKeyPathString!, isEqualTo: value) +} + +public func != (_ keyPath: KeyPath>, _ value: V?) -> Where { - public static func != (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: value) - } + return !Where(keyPath._kvcKeyPathString!, isEqualTo: value) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath>) -> Where where S.Iterator.Element == V { - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where Value == Optional, S.Iterator.Element == V { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) - } + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) } -// MARK: - KeyPath where Root: NSManagedObject, Value: QueryableAttributeType +// MARK: - KeyPath where Root: NSManagedObject, Value: QueryableAttributeType & Comparable -public extension KeyPath where Root: NSManagedObject, Value: QueryableAttributeType { +public func < (_ keyPath: KeyPath, _ value: V) -> Where { - public static func < (_ keyPath: KeyPath, _ value: Value) -> Where { - - return Where("%K < %@", keyPath._kvcKeyPathString!, value) - } + return Where("%K < %@", keyPath._kvcKeyPathString!, value) +} + +public func > (_ keyPath: KeyPath, _ value: V) -> Where { - public static func > (_ keyPath: KeyPath, _ value: Value) -> Where { - - return Where("%K > %@", keyPath._kvcKeyPathString!, value) - } + return Where("%K > %@", keyPath._kvcKeyPathString!, value) +} + +public func <= (_ keyPath: KeyPath, _ value: V) -> Where { - public static func <= (_ keyPath: KeyPath, _ value: Value) -> Where { - - return Where("%K <= %@", keyPath._kvcKeyPathString!, value) - } + return Where("%K <= %@", keyPath._kvcKeyPathString!, value) +} + +public func >= (_ keyPath: KeyPath, _ value: V) -> Where { - public static func >= (_ keyPath: KeyPath, _ value: Value) -> Where { - - return Where("%K >= %@", keyPath._kvcKeyPathString!, value) - } + return Where("%K >= %@", keyPath._kvcKeyPathString!, value) } -// MARK: - KeyPath where Root: NSManagedObject, Value: Optional +// MARK: - KeyPath where Root: NSManagedObject, Value: Optional -public extension KeyPath where Root: NSManagedObject { +public func < (_ keyPath: KeyPath>, _ value: V?) -> Where { - public static func < (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { + if let value = value { - if let value = value { - - return Where("%K < %@", keyPath._kvcKeyPathString!, value) - } - else { - - return Where("%K < nil", keyPath._kvcKeyPathString!) - } + return Where("%K < %@", keyPath._kvcKeyPathString!, value) } - - public static func > (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { + else { - if let value = value { - - return Where("%K > %@", keyPath._kvcKeyPathString!, value) - } - else { - - return Where("%K > nil", keyPath._kvcKeyPathString!) - } + return Where("%K < nil", keyPath._kvcKeyPathString!) } +} + +public func > (_ keyPath: KeyPath>, _ value: V?) -> Where { - public static func <= (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { + if let value = value { - if let value = value { - - return Where("%K <= %@", keyPath._kvcKeyPathString!, value) - } - else { - - return Where("%K <= nil", keyPath._kvcKeyPathString!) - } + return Where("%K > %@", keyPath._kvcKeyPathString!, value) } - - public static func >= (_ keyPath: KeyPath, _ value: Value) -> Where where Value == Optional { + else { - if let value = value { - - return Where("%K >= %@", keyPath._kvcKeyPathString!, value) - } - else { - - return Where("%K >= nil", keyPath._kvcKeyPathString!) - } + return Where("%K > nil", keyPath._kvcKeyPathString!) + } +} + +public func <= (_ keyPath: KeyPath>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K <= %@", keyPath._kvcKeyPathString!, value) + } + else { + + return Where("%K <= nil", keyPath._kvcKeyPathString!) + } +} + +public func >= (_ keyPath: KeyPath>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K >= %@", keyPath._kvcKeyPathString!, value) + } + else { + + return Where("%K >= nil", keyPath._kvcKeyPathString!) } } // MARK: - KeyPath where Root: NSManagedObject, Value: NSManagedObject -public extension KeyPath where Root: NSManagedObject, Value: NSManagedObject { +public func == (_ keyPath: KeyPath, _ object: D) -> Where { - public static func == (_ keyPath: KeyPath, _ object: Value) -> Where { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: object) - } + return Where(keyPath._kvcKeyPathString!, isEqualTo: object) +} + +public func != (_ keyPath: KeyPath, _ object: D) -> Where { - public static func != (_ keyPath: KeyPath, _ object: Value) -> Where { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: object) - } + return !Where(keyPath._kvcKeyPathString!, isEqualTo: object) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == D { - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == Value { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) - } + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) +} + +public func == (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where { - public static func == (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) - } + return Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) +} + +public func != (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where { - public static func != (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) - } + return !Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == NSManagedObjectID { - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where S.Iterator.Element == NSManagedObjectID { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) - } + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) } // MARK: - KeyPath where Root: NSManagedObject, Value: Optional -public extension KeyPath where Root: NSManagedObject { +public func == (_ keyPath: KeyPath>, _ object: D?) -> Where { - public static func == (_ keyPath: KeyPath, _ object: Value) -> Where where Value == Optional { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: object) + return Where(keyPath._kvcKeyPathString!, isEqualTo: object) +} + +public func != (_ keyPath: KeyPath>, _ object: D?) -> Where { + + return !Where(keyPath._kvcKeyPathString!, isEqualTo: object) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath>) -> Where where S.Iterator.Element == D { + + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) +} + +public func == (_ keyPath: KeyPath>, _ objectID: NSManagedObjectID?) -> Where { + + return Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) +} + +public func != (_ keyPath: KeyPath>, _ objectID: NSManagedObjectID?) -> Where { + + return !Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath>) -> Where where S.Iterator.Element == NSManagedObjectID { + + return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) +} + + +// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer.Required + +public func == (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: value) +} + +public func != (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return !Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: value) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath.Required>) -> Where where S.Iterator.Element == V { + + return Where(O.meta[keyPath: keyPath].keyPath, isMemberOf: sequence) +} + + +// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer.Optional + +public func == (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + return Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: value) +} + +public func != (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + return !Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: value) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath.Optional>) -> Where where S.Iterator.Element == V { + + return Where(O.meta[keyPath: keyPath].keyPath, isMemberOf: sequence) +} + + +// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer.Required + +public func < (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return Where("%K < %@", O.meta[keyPath: keyPath].keyPath, value) +} + +public func > (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return Where("%K > %@", O.meta[keyPath: keyPath].keyPath, value) +} + +public func <= (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return Where("%K <= %@", O.meta[keyPath: keyPath].keyPath, value) +} + +public func >= (_ keyPath: KeyPath.Required>, _ value: V) -> Where { + + return Where("%K >= %@", O.meta[keyPath: keyPath].keyPath, value) +} + + +// MARK: - KeyPath where Root: CoreStoreObject, Value: ValueContainer.Optional + +public func < (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K < %@", O.meta[keyPath: keyPath].keyPath, value) } - - public static func != (_ keyPath: KeyPath, _ object: Value) -> Where where Value == Optional { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: object) - } - - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where Value == Optional, S.Iterator.Element == V { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) - } - - public static func == (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where where Value == Optional { - - return Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) - } - - public static func != (_ keyPath: KeyPath, _ objectID: NSManagedObjectID?) -> Where where Value == Optional { - - return !Where(keyPath._kvcKeyPathString!, isEqualTo: objectID) - } - - public static func ~= (_ sequence: S, _ keyPath: KeyPath) -> Where where Value == Optional, S.Iterator.Element == NSManagedObjectID { - - return Where(keyPath._kvcKeyPathString!, isMemberOf: sequence) + else { + + return Where("%K < nil", O.meta[keyPath: keyPath].keyPath) } } + +public func > (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K > %@", O.meta[keyPath: keyPath].keyPath, value) + } + else { + + return Where("%K > nil", O.meta[keyPath: keyPath].keyPath) + } +} + +public func <= (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K <= %@", O.meta[keyPath: keyPath].keyPath, value) + } + else { + + return Where("%K <= nil", O.meta[keyPath: keyPath].keyPath) + } +} + +public func >= (_ keyPath: KeyPath.Optional>, _ value: V?) -> Where { + + if let value = value { + + return Where("%K >= %@", O.meta[keyPath: keyPath].keyPath, value) + } + else { + + return Where("%K >= nil", O.meta[keyPath: keyPath].keyPath) + } +} + + +// MARK: - KeyPath where Root: CoreStoreObject, Value: RelationshipContainer.ToOne + +public func == (_ keyPath: KeyPath.ToOne>, _ object: D) -> Where { + + return Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) +} + +public func != (_ keyPath: KeyPath.ToOne>, _ object: D) -> Where { + + return !Where(O.meta[keyPath: keyPath].keyPath, isEqualTo: object) +} + +public func ~= (_ sequence: S, _ keyPath: KeyPath.ToOne>) -> Where where S.Iterator.Element == D { + + return Where(O.meta[keyPath: keyPath].keyPath, isMemberOf: sequence) +}