Swift 5 support. WIP: Support type-safe predicate expressions

This commit is contained in:
John Estropia
2019-02-01 18:32:22 +09:00
parent 41902fee2e
commit db4426e6b9
15 changed files with 715 additions and 73 deletions

View File

@@ -1232,6 +1232,8 @@ extension NSAttributeType: CoreStoreDebugStringConvertible {
case .objectIDAttributeType: return ".objectIDAttributeType"
case .UUIDAttributeType: return ".UUIDAttributeType"
case .URIAttributeType: return ".URIAttributeType"
@unknown default:
fatalError()
}
}
}
@@ -1254,6 +1256,8 @@ extension NSDeleteRule: CoreStoreDebugStringConvertible {
case .nullifyDeleteRule: return ".nullifyDeleteRule"
case .cascadeDeleteRule: return ".cascadeDeleteRule"
case .denyDeleteRule: return ".denyDeleteRule"
@unknown default:
fatalError()
}
}
}

View File

@@ -66,8 +66,8 @@ extension CoreStore {
internal static func assert( _ condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
self.logger.assert(
condition,
message: message,
condition(),
message: message(),
fileName: fileName,
lineNumber: lineNumber,
functionName: functionName

View File

@@ -47,7 +47,7 @@ public protocol DynamicKeyPath: AnyDynamicKeyPath {
/**
The DynamicObject type
*/
associatedtype ObjectType
associatedtype ObjectType: DynamicObject
/**
The Value type
@@ -66,7 +66,7 @@ extension KeyPathString {
let keyPath = String(keyPath: \Person.nickname)
```
*/
public init<O: NSManagedObject, V>(keyPath: KeyPath<O, V>) {
public init<O: NSManagedObject, V: AllowedObjectiveCKeyPathValue>(keyPath: KeyPath<O, V>) {
self = keyPath.cs_keyPathString
}
@@ -81,18 +81,24 @@ extension KeyPathString {
self = O.meta[keyPath: keyPath].cs_keyPathString
}
/**
Extracts the keyPath string from the property.
```
let keyPath = String(keyPath: \Person.nickname)
```
*/
public init<O: DynamicObject, T, V>(keyPath: Where<O>.Expression<T, V>) {
self = keyPath.cs_keyPathString
}
}
// MARK: - KeyPath: DynamicKeyPath
// TODO: SE-0143 (https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md) is implemented but multiple conformances for the same type currently cannot be declared.
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: ImportableAttributeType
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: ImportableAttributeType?
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: NSManagedObject?
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: NSSet
//extension KeyPath: DynamicKeyPath where Root: NSManagedObject, Value: NSOrderedSet
extension KeyPath: DynamicKeyPath {
extension KeyPath: DynamicKeyPath, AnyDynamicKeyPath where Root: DynamicObject, Value: AllowedObjectiveCKeyPathValue {
public typealias ObjectType = Root
public typealias ValueType = Value

View File

@@ -0,0 +1,140 @@
//
// KeyPathGenericBindings.swift
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreGraphics
import CoreData
// MARK: - AllowedObjectiveCKeyPathValue
/**
Used only for utility methods. Types allowed as `Value` generic type to `KeyPath` utilities.
*/
public protocol AllowedObjectiveCKeyPathValue {}
// MARK: - AllowedOptionalObjectiveCKeyPathValue
/**
Used only for utility methods. Types allowed as `Value` generic type to `KeyPath` utilities.
*/
public protocol AllowedOptionalObjectiveCKeyPathValue: AllowedObjectiveCKeyPathValue {}
extension Bool: AllowedObjectiveCKeyPathValue {}
extension CGFloat: AllowedObjectiveCKeyPathValue {}
extension Data: AllowedOptionalObjectiveCKeyPathValue {}
extension Date: AllowedOptionalObjectiveCKeyPathValue {}
extension Double: AllowedObjectiveCKeyPathValue {}
extension Float: AllowedObjectiveCKeyPathValue {}
extension Int: AllowedObjectiveCKeyPathValue {}
extension Int8: AllowedObjectiveCKeyPathValue {}
extension Int16: AllowedObjectiveCKeyPathValue {}
extension Int32: AllowedObjectiveCKeyPathValue {}
extension Int64: AllowedObjectiveCKeyPathValue {}
extension NSData: AllowedOptionalObjectiveCKeyPathValue {}
extension NSDate: AllowedOptionalObjectiveCKeyPathValue {}
extension NSManagedObject: AllowedOptionalObjectiveCKeyPathValue {}
extension NSNumber: AllowedOptionalObjectiveCKeyPathValue {}
extension NSString: AllowedOptionalObjectiveCKeyPathValue {}
extension NSSet: AllowedOptionalObjectiveCKeyPathValue {}
extension NSOrderedSet: AllowedOptionalObjectiveCKeyPathValue {}
extension NSURL: AllowedOptionalObjectiveCKeyPathValue {}
extension NSUUID: AllowedOptionalObjectiveCKeyPathValue {}
extension String: AllowedOptionalObjectiveCKeyPathValue {}
extension URL: AllowedOptionalObjectiveCKeyPathValue {}
extension UUID: AllowedOptionalObjectiveCKeyPathValue {}
extension Optional: AllowedObjectiveCKeyPathValue where Wrapped: AllowedOptionalObjectiveCKeyPathValue {}
// MARK: - AllowedObjectiveCCollectionKeyPathValue
/**
Used only for utility methods. Types allowed as `Value` generic type to `KeyPath` utilities.
*/
public protocol AllowedObjectiveCCollectionKeyPathValue: AllowedOptionalObjectiveCKeyPathValue {}
extension NSSet: AllowedObjectiveCCollectionKeyPathValue {}
extension NSOrderedSet: AllowedObjectiveCCollectionKeyPathValue {}
extension Optional: AllowedObjectiveCCollectionKeyPathValue, AllowedOptionalObjectiveCKeyPathValue where Wrapped: AllowedObjectiveCCollectionKeyPathValue {}
// MARK: - AllowedCoreStoreObjectKeyPathValue
/**
Used only for utility methods. Types allowed as `Value` generic type to `KeyPath` utilities.
*/
public protocol AllowedCoreStoreObjectKeyPathValue: DynamicKeyPath {}
extension ValueContainer.Required: AllowedCoreStoreObjectKeyPathValue {}
extension ValueContainer.Optional: AllowedCoreStoreObjectKeyPathValue {}
extension TransformableContainer.Required: AllowedCoreStoreObjectKeyPathValue {}
extension TransformableContainer.Optional: AllowedCoreStoreObjectKeyPathValue {}
extension RelationshipContainer.ToOne: AllowedCoreStoreObjectKeyPathValue {}
extension RelationshipContainer.ToManyOrdered: AllowedCoreStoreObjectKeyPathValue {}
extension RelationshipContainer.ToManyUnordered: AllowedCoreStoreObjectKeyPathValue {}
// MARK: - AllowedCoreStoreObjectCollectionKeyPathValue
/**
Used only for utility methods. Types allowed as `Value` generic type to `KeyPath` utilities.
*/
public protocol AllowedCoreStoreObjectCollectionKeyPathValue: AllowedCoreStoreObjectKeyPathValue {}
extension RelationshipContainer.ToManyOrdered: AllowedCoreStoreObjectCollectionKeyPathValue {}
extension RelationshipContainer.ToManyUnordered: AllowedCoreStoreObjectCollectionKeyPathValue {}

View File

@@ -1390,6 +1390,9 @@ extension ListMonitor: FetchedResultsControllerHandler {
"\(String(describing: IndexPath.self)).New": newIndexPath!
]
)
@unknown default:
fatalError()
}
}

View File

@@ -105,9 +105,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
keyPath: keyPath,
inverseKeyPath: { nil },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -140,9 +140,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
keyPath: keyPath,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -175,9 +175,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
keyPath: keyPath,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -210,9 +210,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
keyPath: keyPath,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -354,9 +354,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
maxCount: maxCount,
inverseKeyPath: { nil },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -395,9 +395,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
maxCount: maxCount,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -436,9 +436,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
maxCount: maxCount,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -477,9 +477,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
maxCount: maxCount,
inverseKeyPath: { inverse(D.meta).keyPath },
deleteRule: deleteRule,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -627,9 +627,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
deleteRule: deleteRule,
minCount: minCount,
maxCount: maxCount,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -668,9 +668,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
deleteRule: deleteRule,
minCount: minCount,
maxCount: maxCount,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -709,9 +709,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
deleteRule: deleteRule,
minCount: minCount,
maxCount: maxCount,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}
@@ -750,9 +750,9 @@ public enum RelationshipContainer<O: CoreStoreObject> {
deleteRule: deleteRule,
minCount: minCount,
maxCount: maxCount,
versionHashModifier: versionHashModifier,
renamingIdentifier: renamingIdentifier,
affectedByKeyPaths: affectedByKeyPaths
versionHashModifier: versionHashModifier(),
renamingIdentifier: renamingIdentifier(),
affectedByKeyPaths: affectedByKeyPaths()
)
}

View File

@@ -0,0 +1,304 @@
//
// Where.Expression.swift
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import Foundation
import CoreData
// MARK: - ~
infix operator ~ : AdditionPrecedence
// MARK: - WhereExpressionTrait
public protocol WhereExpressionTrait {}
// MARK: - Where
extension Where {
// MARK: - Expression
public struct Expression<T: WhereExpressionTrait, V>: CustomStringConvertible, DynamicKeyPath {
public typealias Trait = T
// MARK: AnyDynamicKeyPath
public let cs_keyPathString: String
// MARK: DynamicKeyPath
public typealias ObjectType = D
public typealias ValueType = V
// MARK: CustomStringConvertible
public var description: String {
return self.cs_keyPathString
}
// MARK: Internal
internal init(_ component: String) {
self.cs_keyPathString = component
}
internal init(_ component1: String, _ component2: String) {
self.cs_keyPathString = component1 + "." + component2
}
}
// MARK: - SingleTarget
public enum SingleTarget: WhereExpressionTrait {}
// MARK: - CollectionTarget
public enum CollectionTarget: WhereExpressionTrait {}
}
// MARK: - ~ Operator (Where.Expression Creation Operators)
// MARK: ~ where D: NSManagedObject
public func ~<D: NSManagedObject, O: NSManagedObject, V: AllowedObjectiveCKeyPathValue>(_ lhs: KeyPath<D, O>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.SingleTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, V: AllowedObjectiveCKeyPathValue>(_ lhs: KeyPath<D, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.SingleTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, V: AllowedObjectiveCCollectionKeyPathValue>(_ lhs: KeyPath<D, O>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, V: AllowedObjectiveCCollectionKeyPathValue>(_ lhs: KeyPath<D, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, T, V: AllowedObjectiveCKeyPathValue>(_ lhs: Where<D>.Expression<T, O>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<T, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, T, V: AllowedObjectiveCCollectionKeyPathValue>(_ lhs: Where<D>.Expression<T, O>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, T, V: AllowedObjectiveCKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<T, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, T, V: AllowedObjectiveCCollectionKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
public func ~<D: NSManagedObject, O: NSManagedObject, T, C: AllowedObjectiveCCollectionKeyPathValue, V: AllowedObjectiveCKeyPathValue>(_ lhs: Where<D>.Expression<T, C>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init(lhs.cs_keyPathString, rhs.cs_keyPathString)
}
// MARK: - ~ where D: CoreStoreObject
public func ~<D: CoreStoreObject, O: CoreStoreObject, K: AllowedCoreStoreObjectKeyPathValue>(_ lhs: KeyPath<D, RelationshipContainer<D>.ToOne<O>>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<Where<D>.SingleTarget, K.ValueType> where K.ObjectType == O {
return .init(
D.meta[keyPath: lhs].cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, K: AllowedCoreStoreObjectCollectionKeyPathValue>(_ lhs: KeyPath<D, RelationshipContainer<D>.ToOne<O>>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<Where<D>.CollectionTarget, K.ValueType> where K.ObjectType == O {
return .init(
D.meta[keyPath: lhs].cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObjectKeyPathValue>(_ lhs: Where<D>.Expression<T, O>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<T, K.ValueType> where K.ObjectType == O {
return .init(
lhs.cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObjectCollectionKeyPathValue>(_ lhs: Where<D>.Expression<T, O>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<Where<D>.CollectionTarget, K.ValueType> where K.ObjectType == O {
return .init(
lhs.cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObjectKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<T, K.ValueType> where K.ObjectType == O {
return .init(
lhs.cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObjectCollectionKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, K>) -> Where<D>.Expression<Where<D>.CollectionTarget, K.ValueType> where K.ObjectType == O {
return .init(
lhs.cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
public func ~<D: CoreStoreObject, O: CoreStoreObject, T, KC: AllowedCoreStoreObjectCollectionKeyPathValue, KV: AllowedCoreStoreObjectKeyPathValue>(_ lhs: Where<D>.Expression<T, KC>, _ rhs: KeyPath<O, KV>) -> Where<D>.Expression<Where<D>.CollectionTarget, KV.ValueType> where KC.ObjectType == D, KV.ObjectType == O {
return .init(
lhs.cs_keyPathString,
O.meta[keyPath: rhs].cs_keyPathString
)
}
// MARK: - Where.Expression where V: QueryableAttributeType
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func ~= <D, T, V: QueryableAttributeType, S: Sequence>(_ sequence: S, _ expression: Where<D>.Expression<T, V>) -> Where<D> where S.Iterator.Element == V {
return Where<D>(expression.cs_keyPathString, isMemberOf: sequence)
}
// MARK: - Where.Expression where V: Optional<QueryableAttributeType>
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
}
public func ~= <D, T, V: QueryableAttributeType, S: Sequence>(_ sequence: S, _ expression: Where<D>.Expression<T, V?>) -> Where<D> where S.Iterator.Element == V {
return Where<D>(expression.cs_keyPathString, isMemberOf: sequence)
}
// MARK: - Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCCollectionKeyPathValue
extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCCollectionKeyPathValue {
public func count() -> Where<D>.Expression<Where<D>.CollectionTarget, Int> {
return .init(self.cs_keyPathString, "@count")
}
}
// MARK: - Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCKeyPathValue
extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCKeyPathValue {
public func any() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("ANY " + self.cs_keyPathString)
}
public func all() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("ALL " + self.cs_keyPathString)
}
public func none() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("NONE " + self.cs_keyPathString)
}
}
// MARK: - Where.Expression where D: CoreStoreObject, T == Where<D>.CollectionTarget
extension Where.Expression where D: CoreStoreObject, T == Where<D>.CollectionTarget {
public func count() -> Where<D>.Expression<Where<D>.CollectionTarget, Int> {
return .init(self.cs_keyPathString, "@count")
}
public func any() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("ANY " + self.cs_keyPathString)
}
public func all() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("ALL " + self.cs_keyPathString)
}
public func none() -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
return .init("NONE " + self.cs_keyPathString)
}
}

View File

@@ -39,41 +39,41 @@ public protocol WhereClauseType: AnyWhereClause {
associatedtype ObjectType: DynamicObject
}
extension WhereClauseType where Self.ObjectType: CoreStoreObject {
extension WhereClauseType {
/**
Combines two `Where` predicates together using `AND` operator.
- Warning: This operator overload is a workaround for Swift generics' inability to constrain by inheritance (https://bugs.swift.org/browse/SR-5213). In effect, this is less type-safe than other overloads because it allows AND'ing clauses of unrelated `DynamicObject` types.
*/
public static func && <TWhere: WhereClauseType>(left: Self, right: TWhere) -> Self {
return Self.init(NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate]))
public static func && <TWhere: WhereClauseType>(left: Self, right: TWhere) -> Where<Self.ObjectType> {
return .init(NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate]))
}
/**
Combines two `Where` predicates together using `AND` operator.
- Warning: This operator overload is a workaround for Swift generics' inability to constrain by inheritance (https://bugs.swift.org/browse/SR-5213). In effect, this is less type-safe than other overloads because it allows AND'ing clauses of unrelated `DynamicObject` types.
*/
public static func && <TWhere: WhereClauseType>(left: TWhere, right: Self) -> Self {
return Self.init(NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate]))
public static func && <TWhere: WhereClauseType>(left: TWhere, right: Self) -> Where<Self.ObjectType> {
return .init(NSCompoundPredicate(type: .and, subpredicates: [left.predicate, right.predicate]))
}
/**
Combines two `Where` predicates together using `OR` operator.
- Warning: This operator overload is a workaround for Swift generics' inability to constrain by inheritance (https://bugs.swift.org/browse/SR-5213). In effect, this is less type-safe than other overloads because it allows OR'ing clauses of unrelated `DynamicObject` types.
*/
public static func || <TWhere: WhereClauseType>(left: Self, right: TWhere) -> Self {
return Self.init(NSCompoundPredicate(type: .or, subpredicates: [left.predicate, right.predicate]))
public static func || <TWhere: WhereClauseType>(left: Self, right: TWhere) -> Where<Self.ObjectType> {
return .init(NSCompoundPredicate(type: .or, subpredicates: [left.predicate, right.predicate]))
}
/**
Combines two `Where` predicates together using `OR` operator.
- Warning: This operator overload is a workaround for Swift generics' inability to constrain by inheritance (https://bugs.swift.org/browse/SR-5213). In effect, this is less type-safe than other overloads because it allows OR'ing clauses of unrelated `DynamicObject` types.
*/
public static func || <TWhere: WhereClauseType>(left: TWhere, right: Self) -> Self {
return Self.init(NSCompoundPredicate(type: .or, subpredicates: [left.predicate, right.predicate]))
public static func || <TWhere: WhereClauseType>(left: TWhere, right: Self) -> Where<Self.ObjectType> {
return .init(NSCompoundPredicate(type: .or, subpredicates: [left.predicate, right.predicate]))
}
}