From 635201868a6c2a4150a33b918c3a93c14ce07869 Mon Sep 17 00:00:00 2001 From: John Estropia Date: Fri, 8 Feb 2019 17:16:56 +0900 Subject: [PATCH] add comparison operators for Where.Expression --- CoreStoreTests/WhereTests.swift | 51 +++++++++---- Sources/Where.Expression.swift | 127 +++++++++++++++++++++++++++++--- 2 files changed, 154 insertions(+), 24 deletions(-) diff --git a/CoreStoreTests/WhereTests.swift b/CoreStoreTests/WhereTests.swift index 26e9122..b0e2b5f 100644 --- a/CoreStoreTests/WhereTests.swift +++ b/CoreStoreTests/WhereTests.swift @@ -66,14 +66,17 @@ final class WhereTests: XCTestCase { XCTAssertEqual( #keyPath(TestEntity1.testToOne.testEntityID), + (\TestEntity1.testToOne ~ \.testEntityID).description, String(keyPath: \TestEntity1.testToOne ~ \.testEntityID) ) XCTAssertEqual( #keyPath(TestEntity1.testToOne.testToOne.testToManyUnordered), + (\TestEntity1.testToOne ~ \.testToOne ~ \.testToManyUnordered).description, String(keyPath: \TestEntity1.testToOne ~ \.testToOne ~ \.testToManyUnordered) ) XCTAssertEqual( #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered), + (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).description, String(keyPath: \TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered) ) } @@ -81,14 +84,17 @@ final class WhereTests: XCTestCase { XCTAssertEqual( "master.pets", + (\Animal.master ~ \.pets).description, String(keyPath: \Animal.master ~ \.pets) ) XCTAssertEqual( "master.pets.species", + (\Animal.master ~ \.pets ~ \.species).description, String(keyPath: \Animal.master ~ \.pets ~ \.species) ) XCTAssertEqual( "master.pets.master", + (\Animal.master ~ \.pets ~ \.master).description, String(keyPath: \Animal.master ~ \.pets ~ \.master) ) } @@ -96,84 +102,99 @@ final class WhereTests: XCTestCase { XCTAssertEqual( #keyPath(TestEntity1.testToOne.testToManyUnordered) + ".@count", - (\TestEntity1.testToOne ~ \.testToManyUnordered).count().description + (\TestEntity1.testToOne ~ \.testToManyUnordered).count().description, + String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).count()) ) XCTAssertEqual( #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered) + ".@count", - (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).count().description + (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).count().description, + String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).count()) ) } do { XCTAssertEqual( "master.pets.@count", - (\Animal.master ~ \.pets).count().description + (\Animal.master ~ \.pets).count().description, + String(keyPath: (\Animal.master ~ \.pets).count()) ) } do { XCTAssertEqual( "ANY " + #keyPath(TestEntity1.testToOne.testToManyUnordered), - (\TestEntity1.testToOne ~ \.testToManyUnordered).any().description + (\TestEntity1.testToOne ~ \.testToManyUnordered).any().description, + String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).any()) ) XCTAssertEqual( "ANY " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered), - (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).any().description + (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).any().description, + String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).any()) ) } do { XCTAssertEqual( "ANY master.pets", - (\Animal.master ~ \.pets).any().description + (\Animal.master ~ \.pets).any().description, + String(keyPath: (\Animal.master ~ \.pets).any()) ) XCTAssertEqual( "ANY master.pets.species", - (\Animal.master ~ \.pets ~ \.species).any().description + (\Animal.master ~ \.pets ~ \.species).any().description, + String(keyPath: (\Animal.master ~ \.pets ~ \.species).any()) ) } do { XCTAssertEqual( "ALL " + #keyPath(TestEntity1.testToOne.testToManyUnordered), - (\TestEntity1.testToOne ~ \.testToManyUnordered).all().description + (\TestEntity1.testToOne ~ \.testToManyUnordered).all().description, + String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).all()) ) XCTAssertEqual( "ALL " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered), - (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).all().description + (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).all().description, + String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).all()) ) } do { XCTAssertEqual( "ALL master.pets", - (\Animal.master ~ \.pets).all().description + (\Animal.master ~ \.pets).all().description, + String(keyPath: (\Animal.master ~ \.pets).all()) ) XCTAssertEqual( "ALL master.pets.species", - (\Animal.master ~ \.pets ~ \.species).all().description + (\Animal.master ~ \.pets ~ \.species).all().description, + String(keyPath: (\Animal.master ~ \.pets ~ \.species).all()) ) } do { XCTAssertEqual( "NONE " + #keyPath(TestEntity1.testToOne.testToManyUnordered), - (\TestEntity1.testToOne ~ \.testToManyUnordered).none().description + (\TestEntity1.testToOne ~ \.testToManyUnordered).none().description, + String(keyPath: (\TestEntity1.testToOne ~ \.testToManyUnordered).none()) ) XCTAssertEqual( "NONE " + #keyPath(TestEntity2.testToOne.testToOne.testToManyOrdered), - (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).none().description + (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).none().description, + String(keyPath: (\TestEntity2.testToOne ~ \.testToOne ~ \.testToManyOrdered).none()) ) } do { XCTAssertEqual( "NONE master.pets", - (\Animal.master ~ \.pets).none().description + (\Animal.master ~ \.pets).none().description, + String(keyPath: (\Animal.master ~ \.pets).none()) ) XCTAssertEqual( "NONE master.pets.species", - (\Animal.master ~ \.pets ~ \.species).none().description + (\Animal.master ~ \.pets ~ \.species).none().description, + String(keyPath: (\Animal.master ~ \.pets ~ \.species).none()) ) } } diff --git a/Sources/Where.Expression.swift b/Sources/Where.Expression.swift index c31f92b..11c4fd1 100644 --- a/Sources/Where.Expression.swift +++ b/Sources/Where.Expression.swift @@ -91,7 +91,7 @@ extension Where { } -// MARK: - ~ Operator (Where.Expression Creation Operators) +// MARK: - ~ (Where.Expression Creation Operators) // MARK: ~ where D: NSManagedObject @@ -218,6 +218,29 @@ public func ~= (_ sequence: S, _ e } +// MARK: - Where.Expression where V: QueryableAttributeType & Comparable + +public func < (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: "<", operand: rhs) +} + +public func <= (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: "<=", operand: rhs) +} + +public func > (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: ">", operand: rhs) +} + +public func >= (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: ">=", operand: rhs) +} + + // MARK: - Where.Expression where V: Optional public func == (_ lhs: Where.Expression, _ rhs: V) -> Where { @@ -246,11 +269,44 @@ public func ~= (_ sequence: S, _ e } +// MARK: - Where.Expression where V: Optional + +public func < (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: "<", operand: rhs) +} + +public func <= (_ lhs: Where.Expression, _ rhs: V?) -> Where { + + return Where(expression: lhs, function: "<=", operand: rhs) +} + +public func > (_ lhs: Where.Expression, _ rhs: V) -> Where { + + return Where(expression: lhs, function: ">", operand: rhs) +} + +public func >= (_ lhs: Where.Expression, _ rhs: V?) -> Where { + + return Where(expression: lhs, function: ">=", operand: rhs) +} + + +// MARK: - KeyPath where Root: NSManagedObject, Value: AllowedObjectiveCCollectionKeyPathValue + +extension KeyPath where Root: NSManagedObject, Value: AllowedObjectiveCCollectionKeyPathValue { + + public func count() -> Where.Expression.CollectionTarget, Int> { + + return .init(self.cs_keyPathString, "@count") + } +} + // MARK: - Where.Expression where D: NSManagedObject, T == Where.CollectionTarget, V: AllowedObjectiveCCollectionKeyPathValue extension Where.Expression where D: NSManagedObject, T == Where.CollectionTarget, V: AllowedObjectiveCCollectionKeyPathValue { - public func count() -> Where.Expression.CollectionTarget, Int> { + public func count() -> Where.Expression { return .init(self.cs_keyPathString, "@count") } @@ -261,44 +317,97 @@ extension Where.Expression where D: NSManagedObject, T == Where.CollectionTar extension Where.Expression where D: NSManagedObject, T == Where.CollectionTarget, V: AllowedObjectiveCKeyPathValue { - public func any() -> Where.Expression.CollectionTarget, V> { + public func any() -> Where.Expression { return .init("ANY " + self.cs_keyPathString) } - public func all() -> Where.Expression.CollectionTarget, V> { + public func all() -> Where.Expression { return .init("ALL " + self.cs_keyPathString) } - public func none() -> Where.Expression.CollectionTarget, V> { + public func none() -> Where.Expression { return .init("NONE " + self.cs_keyPathString) } } +// MARK: - KeyPath where Root: CoreStoreObject, Value: AllowedObjectiveCCollectionKeyPathValue + +extension KeyPath where Root: CoreStoreObject, Value: AllowedCoreStoreObjectCollectionKeyPathValue { + + public func count() -> Where.Expression.CollectionTarget, Int> { + + return .init(Root.meta[keyPath: self].cs_keyPathString, "@count") + } +} + + // MARK: - Where.Expression where D: CoreStoreObject, T == Where.CollectionTarget extension Where.Expression where D: CoreStoreObject, T == Where.CollectionTarget { - public func count() -> Where.Expression.CollectionTarget, Int> { + public func count() -> Where.Expression { return .init(self.cs_keyPathString, "@count") } - public func any() -> Where.Expression.CollectionTarget, V> { + public func any() -> Where.Expression { return .init("ANY " + self.cs_keyPathString) } - public func all() -> Where.Expression.CollectionTarget, V> { + public func all() -> Where.Expression { return .init("ALL " + self.cs_keyPathString) } - public func none() -> Where.Expression.CollectionTarget, V> { + public func none() -> Where.Expression { return .init("NONE " + self.cs_keyPathString) } } + + +// MARK: - Where + +extension Where { + + // MARK: FilePrivate + + fileprivate init(expression: Where.Expression, function: String, operand: V) { + + self.init("\(expression.cs_keyPathString) \(function) %@", operand.cs_toQueryableNativeType()) + } + + fileprivate init(expression: Where.Expression, function: String, operand: V) { + + self.init("\(expression.cs_keyPathString) \(function) %@", operand.cs_toQueryableNativeType()) + } + + fileprivate init(expression: Where.Expression, function: String, operand: V?) { + + if let operand = operand { + + self.init("\(expression.cs_keyPathString) \(function) %@", operand.cs_toQueryableNativeType()) + } + else { + + self.init("\(expression.cs_keyPathString) \(function) nil") + } + } + + fileprivate init(expression: Where.Expression, function: String, operand: V?) { + + if let operand = operand { + + self.init("\(expression.cs_keyPathString) \(function) %@", operand.cs_toQueryableNativeType()) + } + else { + + self.init("\(expression.cs_keyPathString) \(function) nil") + } + } +}