mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-12 20:30:30 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c282b18af | ||
|
|
ebbde8b7b6 | ||
|
|
a1407e4121 | ||
|
|
99b871b97a | ||
|
|
1cd3c4fcf4 | ||
|
|
e09ac9ee00 | ||
|
|
4b0d134acb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@ CoreStore.xcworkspace/xcuserdata
|
||||
DerivedData
|
||||
*.orig
|
||||
build
|
||||
Playground_macOS.playground/playground.xcworkspace/xcuserdata
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "CoreStore"
|
||||
s.version = "6.0.0"
|
||||
s.version = "6.2.0"
|
||||
s.swift_version = "4.2"
|
||||
s.license = "MIT"
|
||||
s.homepage = "https://github.com/JohnEstropia/CoreStore"
|
||||
|
||||
@@ -880,6 +880,8 @@
|
||||
B5A1DAC71F111BFA003CF369 /* KeyPath+Querying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KeyPath+Querying.swift"; sourceTree = "<group>"; };
|
||||
B5A261201B64BFDB006EB6D3 /* MigrationType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationType.swift; sourceTree = "<group>"; };
|
||||
B5A5F2651CAEC50F004AB9AF /* CSSelect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSSelect.swift; sourceTree = "<group>"; };
|
||||
B5A80DF42212C1AB006096AA /* Playground_macOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground_macOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
B5A80DF52212C1BC006096AA /* Playground_iOS.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground_iOS.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
B5A991EB1E9DC2CE0091A2E3 /* VersionLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionLock.swift; sourceTree = "<group>"; };
|
||||
B5A9921E1EA898710091A2E3 /* UserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; };
|
||||
B5AD60CD1C90141E00F2B2E8 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
|
||||
@@ -961,7 +963,6 @@
|
||||
B5E84F351AFF85470064E85B /* NSManagedObjectContext+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectContext+Querying.swift"; sourceTree = "<group>"; };
|
||||
B5E84F401AFF8CCD0064E85B /* TypeErasedClauses.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeErasedClauses.swift; sourceTree = "<group>"; };
|
||||
B5E8A71F21C1015300EF006A /* CoreStoreObject+Observing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoreStoreObject+Observing.swift"; sourceTree = "<group>"; };
|
||||
B5E8A72621C3B85000EF006A /* Playground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Playground.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
B5ECDBDE1CA6BB2B00C7F112 /* CSBaseDataTransaction+Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CSBaseDataTransaction+Querying.swift"; sourceTree = "<group>"; };
|
||||
B5ECDBE41CA6BEA300C7F112 /* CSClauseTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSClauseTypes.swift; sourceTree = "<group>"; };
|
||||
B5ECDBEB1CA6BF2000C7F112 /* CSFrom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CSFrom.swift; sourceTree = "<group>"; };
|
||||
@@ -1052,7 +1053,8 @@
|
||||
2F03A52619C5C6DA005002A5 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B5E8A72621C3B85000EF006A /* Playground.playground */,
|
||||
B5A80DF52212C1BC006096AA /* Playground_iOS.playground */,
|
||||
B5A80DF42212C1AB006096AA /* Playground_macOS.playground */,
|
||||
2F291E3119C6D4D3007AF63F /* Frameworks */,
|
||||
2F03A53219C5C6DA005002A5 /* Sources */,
|
||||
2F03A53C19C5C6DA005002A5 /* CoreStoreTests */,
|
||||
|
||||
@@ -313,6 +313,7 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
|
||||
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
|
||||
|
||||
self.setTable(enabled: false)
|
||||
ColorsDemo.stack.perform(
|
||||
asynchronous: { (transaction) in
|
||||
|
||||
@@ -322,12 +323,16 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
palette.colorName .= nil
|
||||
}
|
||||
},
|
||||
completion: { _ in }
|
||||
completion: { _ in
|
||||
|
||||
self.setTable(enabled: true)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private func setTable(enabled: Bool) {
|
||||
|
||||
|
||||
tableView.isUserInteractionEnabled = enabled
|
||||
UIView.animate(
|
||||
withDuration: 0.2,
|
||||
delay: 0,
|
||||
@@ -337,7 +342,6 @@ class ListObserverDemoViewController: UITableViewController, ListSectionObserver
|
||||
if let tableView = self.tableView {
|
||||
|
||||
tableView.alpha = enabled ? 1.0 : 0.5
|
||||
tableView.isUserInteractionEnabled = enabled
|
||||
}
|
||||
},
|
||||
completion: nil
|
||||
|
||||
@@ -141,10 +141,8 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
let k1 = String(keyPath: \Animal.species)
|
||||
XCTAssertEqual(k1, "species")
|
||||
|
||||
#if swift(<5.0)
|
||||
let k2 = String(keyPath: \Dog.species)
|
||||
XCTAssertEqual(k2, "species")
|
||||
#endif
|
||||
|
||||
let k3 = String(keyPath: \Dog.nickname)
|
||||
XCTAssertEqual(k3, "nickname")
|
||||
@@ -325,9 +323,7 @@ class DynamicModelTests: BaseTestDataTestCase {
|
||||
dynamic func test_ThatDynamicModelKeyPaths_CanBeCreated() {
|
||||
|
||||
XCTAssertEqual(String(keyPath: \Animal.species), "species")
|
||||
#if swift(<5.0)
|
||||
XCTAssertEqual(String(keyPath: \Dog.species), "species")
|
||||
#endif
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>6.0.0</string>
|
||||
<string>6.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import UIKit
|
||||
import CoreStore
|
||||
|
||||
/// Model Declaration =====
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species", initial: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<UIColor>("color", initial: .orange)
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Optional<String>("name")
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
}
|
||||
/// =======================
|
||||
|
||||
/// Stack setup ===========
|
||||
let dataStack = DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Person>("Person")
|
||||
]
|
||||
)
|
||||
)
|
||||
try dataStack.addStorageAndWait(SQLiteStore(fileName: "data.sqlite"))
|
||||
/// =======================
|
||||
|
||||
/// Transactions ==========
|
||||
dataStack.perform(synchronous: { transaction in
|
||||
|
||||
let animal = transaction.create(Into<Animal>())
|
||||
animal.species .= "Sparrow"
|
||||
animal.color .= .yellow
|
||||
|
||||
let person = transaction.create(Into<Person>())
|
||||
person.name .= "John"
|
||||
person.pets.value.insert(animal)
|
||||
})
|
||||
/// =======================
|
||||
|
||||
/// Accessing Objects =====
|
||||
let bird = dataStack.fetchOne(From<Animal>().where(\.species == "Sparrow"))!
|
||||
bird.species.value
|
||||
bird.color.value
|
||||
print(bird)
|
||||
|
||||
let owner = bird.master.value!
|
||||
owner.name.value
|
||||
owner.pets.count
|
||||
print(owner)
|
||||
/// =======================
|
||||
79
Playground_iOS.playground/Contents.swift
Normal file
79
Playground_iOS.playground/Contents.swift
Normal file
@@ -0,0 +1,79 @@
|
||||
import UIKit
|
||||
import CoreStore
|
||||
import PlaygroundSupport
|
||||
|
||||
PlaygroundPage.current.needsIndefiniteExecution = true
|
||||
|
||||
/// Model Declaration =====
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species", initial: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<UIColor>("color", initial: .orange)
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Optional<String>("name")
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
}
|
||||
/// =======================
|
||||
|
||||
/// Stack setup ===========
|
||||
let dataStack = DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Person>("Person")
|
||||
]
|
||||
)
|
||||
)
|
||||
dataStack.addStorage(
|
||||
SQLiteStore(fileName: "data.sqlite"),
|
||||
completion: { result in
|
||||
|
||||
switch result {
|
||||
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
|
||||
case .success:
|
||||
/// Transactions ==========
|
||||
dataStack.perform(
|
||||
asynchronous: { transaction in
|
||||
|
||||
let animal = transaction.create(Into<Animal>())
|
||||
animal.species .= "Sparrow"
|
||||
animal.color .= .yellow
|
||||
|
||||
let person = transaction.create(Into<Person>())
|
||||
person.name .= "John"
|
||||
person.pets.value.insert(animal)
|
||||
},
|
||||
completion: { result in
|
||||
|
||||
switch result {
|
||||
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
|
||||
case .success:
|
||||
/// Accessing Objects =====
|
||||
let bird = try! dataStack.fetchOne(From<Animal>().where(\.species == "Sparrow"))!
|
||||
print(bird.species.value)
|
||||
print(bird.color.value as Any)
|
||||
print(bird)
|
||||
|
||||
let owner = bird.master.value!
|
||||
print(owner.name.value as Any)
|
||||
print(owner.pets.count)
|
||||
print(owner)
|
||||
/// =======================
|
||||
}
|
||||
}
|
||||
)
|
||||
/// =======================
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
77
Playground_macOS.playground/Contents.swift
Normal file
77
Playground_macOS.playground/Contents.swift
Normal file
@@ -0,0 +1,77 @@
|
||||
import AppKit
|
||||
import CoreStore
|
||||
import PlaygroundSupport
|
||||
|
||||
PlaygroundPage.current.needsIndefiniteExecution = true
|
||||
|
||||
/// Model Declaration =====
|
||||
class Animal: CoreStoreObject {
|
||||
let species = Value.Required<String>("species", initial: "Swift")
|
||||
let master = Relationship.ToOne<Person>("master")
|
||||
let color = Transformable.Optional<NSColor>("color", initial: .orange)
|
||||
}
|
||||
|
||||
class Person: CoreStoreObject {
|
||||
let name = Value.Optional<String>("name")
|
||||
let pets = Relationship.ToManyUnordered<Animal>("pets", inverse: { $0.master })
|
||||
}
|
||||
/// =======================
|
||||
|
||||
/// Stack setup ===========
|
||||
let dataStack = DataStack(
|
||||
CoreStoreSchema(
|
||||
modelVersion: "V1",
|
||||
entities: [
|
||||
Entity<Animal>("Animal"),
|
||||
Entity<Person>("Person")
|
||||
]
|
||||
)
|
||||
)
|
||||
dataStack.addStorage(
|
||||
SQLiteStore(fileName: "data.sqlite"),
|
||||
completion: { result in
|
||||
|
||||
switch result {
|
||||
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
|
||||
case .success:
|
||||
/// Transactions ==========
|
||||
dataStack.perform(
|
||||
asynchronous: { transaction in
|
||||
|
||||
let animal = transaction.create(Into<Animal>())
|
||||
animal.species .= "Sparrow"
|
||||
animal.color .= .yellow
|
||||
|
||||
let person = transaction.create(Into<Person>())
|
||||
person.name .= "John"
|
||||
person.pets.value.insert(animal)
|
||||
},
|
||||
completion: { result in
|
||||
|
||||
switch result {
|
||||
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
|
||||
case .success:
|
||||
/// Accessing Objects =====
|
||||
let bird = try! dataStack.fetchOne(From<Animal>().where(\.species == "Sparrow"))!
|
||||
print(bird.species.value)
|
||||
print(bird.color.value as Any)
|
||||
print(bird)
|
||||
|
||||
let owner = bird.master.value!
|
||||
print(owner.name.value as Any)
|
||||
print(owner.pets.count)
|
||||
print(owner)
|
||||
/// =======================
|
||||
}
|
||||
}
|
||||
)
|
||||
/// =======================
|
||||
}
|
||||
}
|
||||
)
|
||||
4
Playground_macOS.playground/contents.xcplayground
Normal file
4
Playground_macOS.playground/contents.xcplayground
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'>
|
||||
<timeline fileName='timeline.xctimeline'/>
|
||||
</playground>
|
||||
7
Playground_macOS.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
Playground_macOS.playground/playground.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1872,7 +1872,7 @@ Once the version lock is set, any changes in the properties or to the model will
|
||||
### Install with CocoaPods
|
||||
In your `Podfile`, add
|
||||
```
|
||||
pod 'CoreStore', '~> 6.0'
|
||||
pod 'CoreStore', '~> 6.1'
|
||||
```
|
||||
and run
|
||||
```
|
||||
@@ -1883,7 +1883,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
|
||||
### Install with Carthage
|
||||
In your `Cartfile`, add
|
||||
```
|
||||
github "JohnEstropia/CoreStore" >= 6.0.0
|
||||
github "JohnEstropia/CoreStore" >= 6.2.0
|
||||
```
|
||||
and run
|
||||
```
|
||||
@@ -1894,7 +1894,7 @@ This installs CoreStore as a framework. Declare `import CoreStore` in your swift
|
||||
#### Install with Swift Package Manager:
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "6.0.0"))
|
||||
.package(url: "https://github.com/JohnEstropia/CoreStore.git", from: "6.2.0"))
|
||||
]
|
||||
```
|
||||
Declare `import CoreStore` in your swift file to use the library.
|
||||
|
||||
@@ -100,8 +100,7 @@ public final class Entity<O: CoreStoreObject>: DynamicEntity {
|
||||
entityName,
|
||||
isAbstract: isAbstract,
|
||||
versionHashModifier: versionHashModifier,
|
||||
indexes: indexes,
|
||||
uniqueConstraints: []
|
||||
indexes: indexes
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,14 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) {}
|
||||
else {
|
||||
|
||||
self.deletedSections = []
|
||||
self.insertedSections = []
|
||||
}
|
||||
|
||||
self.handler?.controllerWillChangeContent(controller)
|
||||
}
|
||||
|
||||
@@ -100,6 +108,7 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
self.handler?.controllerDidChangeContent(controller)
|
||||
}
|
||||
|
||||
@@ -110,11 +119,102 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) {
|
||||
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
atIndexPath: indexPath,
|
||||
forChangeType: type,
|
||||
newIndexPath: newIndexPath
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
guard var actualType = NSFetchedResultsChangeType(rawValue: type.rawValue) else {
|
||||
|
||||
// This fix is for a bug where iOS passes 0 for NSFetchedResultsChangeType, but this is not a valid enum case.
|
||||
// Swift will then always execute the first case of the switch causing strange behaviour.
|
||||
// https://forums.developer.apple.com/thread/12184#31850
|
||||
return
|
||||
}
|
||||
|
||||
// This whole dance is a workaround for a nasty bug introduced in XCode 7 targeted at iOS 8 devices
|
||||
// http://stackoverflow.com/questions/31383760/ios-9-attempt-to-delete-and-reload-the-same-index-path/31384014#31384014
|
||||
// https://forums.developer.apple.com/message/9998#9998
|
||||
// https://forums.developer.apple.com/message/31849#31849
|
||||
|
||||
if case .update = actualType,
|
||||
indexPath != nil,
|
||||
newIndexPath != nil {
|
||||
|
||||
actualType = .move
|
||||
}
|
||||
|
||||
switch actualType {
|
||||
|
||||
case .update:
|
||||
guard let section = indexPath?[0] else {
|
||||
|
||||
return
|
||||
}
|
||||
if self.deletedSections.contains(section)
|
||||
|| self.insertedSections.contains(section) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
case .move:
|
||||
guard let indexPath = indexPath, let newIndexPath = newIndexPath else {
|
||||
|
||||
return
|
||||
}
|
||||
guard indexPath == newIndexPath else {
|
||||
|
||||
break
|
||||
}
|
||||
if self.insertedSections.contains(indexPath[0]) {
|
||||
|
||||
// Observers that handle the .Move change are advised to delete then reinsert the object instead of just moving. This is especially true when indexPath and newIndexPath are equal. For example, calling tableView.moveRowAtIndexPath(_:toIndexPath) when both indexPaths are the same will crash the tableView.
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
atIndexPath: indexPath,
|
||||
forChangeType: .move,
|
||||
newIndexPath: newIndexPath
|
||||
)
|
||||
return
|
||||
}
|
||||
if self.deletedSections.contains(indexPath[0]) {
|
||||
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
atIndexPath: nil,
|
||||
forChangeType: .insert,
|
||||
newIndexPath: indexPath
|
||||
)
|
||||
return
|
||||
}
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
atIndexPath: indexPath,
|
||||
forChangeType: .update,
|
||||
newIndexPath: nil
|
||||
)
|
||||
return
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeObject: anObject,
|
||||
atIndexPath: indexPath,
|
||||
forChangeType: type,
|
||||
forChangeType: actualType,
|
||||
newIndexPath: newIndexPath
|
||||
)
|
||||
}
|
||||
@@ -126,6 +226,18 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if #available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) {}
|
||||
else {
|
||||
|
||||
switch type {
|
||||
|
||||
case .delete: self.deletedSections.insert(sectionIndex)
|
||||
case .insert: self.insertedSections.insert(sectionIndex)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
self.handler?.controller(
|
||||
controller,
|
||||
didChangeSection: sectionInfo,
|
||||
@@ -142,4 +254,13 @@ internal final class FetchedResultsControllerDelegate: NSObject, NSFetchedResult
|
||||
sectionIndexTitleForSectionName: sectionName
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
@nonobjc
|
||||
private var deletedSections = Set<Int>()
|
||||
|
||||
@nonobjc
|
||||
private var insertedSections = Set<Int>()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>6.0.0</string>
|
||||
<string>6.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
||||
@@ -29,11 +29,24 @@ import CoreData
|
||||
|
||||
// MARK: - ~
|
||||
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(
|
||||
From<Pet>().where(
|
||||
(\.master ~ \.name) == "John"
|
||||
)
|
||||
)
|
||||
```
|
||||
*/
|
||||
infix operator ~ : AdditionPrecedence
|
||||
|
||||
|
||||
// MARK: - WhereExpressionTrait
|
||||
|
||||
/**
|
||||
Used only for `Where.Expression` type constraints. Currently supports `SingleTarget` and `CollectionTarget`.
|
||||
*/
|
||||
public protocol WhereExpressionTrait {}
|
||||
|
||||
|
||||
@@ -43,8 +56,20 @@ extension Where {
|
||||
|
||||
// MARK: - Expression
|
||||
|
||||
/**
|
||||
Type-safe keyPath chain usable in query/fetch expressions.
|
||||
```
|
||||
let expression: Where<Pet>.Expression = (\.master ~ \.name)
|
||||
let owner = CoreStore.fetchOne(
|
||||
From<Pet>().where(expression == "John")
|
||||
)
|
||||
```
|
||||
*/
|
||||
public struct Expression<T: WhereExpressionTrait, V>: CustomStringConvertible, DynamicKeyPath {
|
||||
|
||||
/**
|
||||
Currently supports `SingleTarget` and `CollectionTarget`.
|
||||
*/
|
||||
public typealias Trait = T
|
||||
|
||||
|
||||
@@ -83,10 +108,17 @@ extension Where {
|
||||
|
||||
// MARK: - SingleTarget
|
||||
|
||||
/**
|
||||
Used only for `Where.Expression` type constraints. Specifies that this `Where.Expression` type pertains to an attribute property expression.
|
||||
*/
|
||||
public enum SingleTarget: WhereExpressionTrait {}
|
||||
|
||||
|
||||
// MARK: - CollectionTarget
|
||||
|
||||
/**
|
||||
Used only for `Where.Expression` type constraints. Specifies that this `Where.Expression` type pertains to a to-many relationship expression.
|
||||
*/
|
||||
public enum CollectionTarget: WhereExpressionTrait {}
|
||||
}
|
||||
|
||||
@@ -95,47 +127,101 @@ extension Where {
|
||||
|
||||
// MARK: ~ where D: NSManagedObject
|
||||
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(From<Pet>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(From<Pet>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let happyPets = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let happyPets = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let johnsSonInLaw = CoreStore.fetchOne(From<Person>().where((\.spouse ~ \.father ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let johnsSonInLaw = CoreStore.fetchOne(From<Person>().where((\.spouse ~ \.father ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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: AllowedObjectiveCKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<T, V> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let spouseHasSiblings = CoreStore.fetchOne(From<Person>().where((\.spouse ~ \.father ~ \.children).count() > 0))
|
||||
```
|
||||
*/
|
||||
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: AllowedObjectiveCCollectionKeyPathValue>(_ lhs: Where<D>.Expression<T, O?>, _ rhs: KeyPath<O, V>) -> Where<D>.Expression<Where<D>.CollectionTarget, V> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let spouseHasSiblings = CoreStore.fetchOne(From<Person>().where((\.spouse ~ \.father ~ \.children).count() > 0))
|
||||
```
|
||||
*/
|
||||
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> {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let spousesWithBadNamingSense = CoreStore.fetchAll(From<Person>().where((\.spouse ~ \.pets ~ \.name).any() == "Spot"))
|
||||
```
|
||||
*/
|
||||
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)
|
||||
}
|
||||
@@ -143,7 +229,13 @@ public func ~<D: NSManagedObject, O: NSManagedObject, T, C: AllowedObjectiveCCol
|
||||
|
||||
// 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 {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(From<Pet>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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,
|
||||
@@ -151,7 +243,41 @@ public func ~<D: CoreStoreObject, O: CoreStoreObject, K: AllowedCoreStoreObjectK
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(From<Pet>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let owner = CoreStore.fetchOne(From<Pet>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let happyPets = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
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,
|
||||
@@ -159,7 +285,13 @@ public func ~<D: CoreStoreObject, O: CoreStoreObject, K: AllowedCoreStoreObjectC
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let happyPets = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
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,
|
||||
@@ -167,7 +299,13 @@ public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObje
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let happyPets = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
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,
|
||||
@@ -175,23 +313,13 @@ public func ~<D: CoreStoreObject, O: CoreStoreObject, T, K: AllowedCoreStoreObje
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
/**
|
||||
Connects multiple `DynamicKeyPath`s to create a type-safe chain usable in query/fetch expressions
|
||||
```
|
||||
let spousesWithBadNamingSense = CoreStore.fetchAll(From<Pet>().where((\.master ~ \.pets ~ \.name).any() == "Spot"))
|
||||
```
|
||||
*/
|
||||
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,
|
||||
@@ -202,16 +330,34 @@ public func ~<D: CoreStoreObject, O: CoreStoreObject, T, KC: AllowedCoreStoreObj
|
||||
|
||||
// MARK: - Where.Expression where V: QueryableAttributeType
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is not equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) != "John"))
|
||||
```
|
||||
*/
|
||||
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by checking if a sequence contains a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where(["John", "Joe"] ~= (\.master ~ \.name))
|
||||
```
|
||||
*/
|
||||
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)
|
||||
@@ -220,21 +366,45 @@ public func ~= <D, T, V: QueryableAttributeType, S: Sequence>(_ sequence: S, _ e
|
||||
|
||||
// MARK: - Where.Expression where V: QueryableAttributeType & Comparable
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is less than a value
|
||||
```
|
||||
let lonelyDog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.pets).count() < 2))
|
||||
```
|
||||
*/
|
||||
public func < <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: "<", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is less than or equal to a value
|
||||
```
|
||||
let lonelyDog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.pets).count() <= 1)
|
||||
```
|
||||
*/
|
||||
public func <= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: "<=", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is greater than a value
|
||||
```
|
||||
let happyDog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.pets).count() > 1)
|
||||
```
|
||||
*/
|
||||
public func > <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: ">", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is greater than or equal to a value
|
||||
```
|
||||
let happyDog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.pets).count() >= 2)
|
||||
```
|
||||
*/
|
||||
public func >= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: ">=", operand: rhs)
|
||||
@@ -243,26 +413,56 @@ public func >= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Ex
|
||||
|
||||
// MARK: - Where.Expression where V: Optional<QueryableAttributeType>
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) == "John"))
|
||||
```
|
||||
*/
|
||||
public func == <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
|
||||
|
||||
return Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) != "John"))
|
||||
```
|
||||
*/
|
||||
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is equal to a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.name) != "John"))
|
||||
```
|
||||
*/
|
||||
public func != <D, T, V: QueryableAttributeType>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
|
||||
|
||||
return !Where<D>(lhs.cs_keyPathString, isEqualTo: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by checking if a sequence contains a value
|
||||
```
|
||||
let dog = CoreStore.fetchOne(From<Dog>().where(["John", "Joe"] ~= (\.master ~ \.name))
|
||||
```
|
||||
*/
|
||||
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)
|
||||
@@ -271,21 +471,45 @@ public func ~= <D, T, V: QueryableAttributeType, S: Sequence>(_ sequence: S, _ e
|
||||
|
||||
// MARK: - Where.Expression where V: Optional<QueryableAttributeType & Comparable>
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is less than a value
|
||||
```
|
||||
let childsPet = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.age) < 10))
|
||||
```
|
||||
*/
|
||||
public func < <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: "<", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is less than or equal to a value
|
||||
```
|
||||
let childsPet = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.age) <= 10))
|
||||
```
|
||||
*/
|
||||
public func <= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: "<=", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is greater than a value
|
||||
```
|
||||
let teensPet = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.age) > 10))
|
||||
```
|
||||
*/
|
||||
public func > <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: ">", operand: rhs)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where` clause by comparing if an expression is greater than or equal to a value
|
||||
```
|
||||
let teensPet = CoreStore.fetchOne(From<Dog>().where((\.master ~ \.age) >= 10))
|
||||
```
|
||||
*/
|
||||
public func >= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Expression<T, V?>, _ rhs: V?) -> Where<D> {
|
||||
|
||||
return Where<D>(expression: lhs, function: ">=", operand: rhs)
|
||||
@@ -296,6 +520,12 @@ public func >= <D, T, V: QueryableAttributeType & Comparable>(_ lhs: Where<D>.Ex
|
||||
|
||||
extension KeyPath where Root: NSManagedObject, Value: AllowedObjectiveCCollectionKeyPathValue {
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for COUNT
|
||||
```
|
||||
let dogsWithPlaymates = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
public func count() -> Where<Root>.Expression<Where<Root>.CollectionTarget, Int> {
|
||||
|
||||
return .init(self.cs_keyPathString, "@count")
|
||||
@@ -306,6 +536,12 @@ extension KeyPath where Root: NSManagedObject, Value: AllowedObjectiveCCollectio
|
||||
|
||||
extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCCollectionKeyPathValue {
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for COUNT
|
||||
```
|
||||
let dogsWithPlaymates = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
public func count() -> Where<D>.Expression<T, Int> {
|
||||
|
||||
return .init(self.cs_keyPathString, "@count")
|
||||
@@ -317,16 +553,34 @@ extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTar
|
||||
|
||||
extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTarget, V: AllowedObjectiveCKeyPathValue {
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for ANY
|
||||
```
|
||||
let dogsWithBadNamingSense = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.name).any() > "Spot"))
|
||||
```
|
||||
*/
|
||||
public func any() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("ANY " + self.cs_keyPathString)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for ALL
|
||||
```
|
||||
let allPlaymatePuppies = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.age).all() > 5))
|
||||
```
|
||||
*/
|
||||
public func all() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("ALL " + self.cs_keyPathString)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for NONE
|
||||
```
|
||||
let dogs = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.name).any() > "Spot"))
|
||||
```
|
||||
*/
|
||||
public func none() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("NONE " + self.cs_keyPathString)
|
||||
@@ -338,6 +592,12 @@ extension Where.Expression where D: NSManagedObject, T == Where<D>.CollectionTar
|
||||
|
||||
extension KeyPath where Root: CoreStoreObject, Value: AllowedCoreStoreObjectCollectionKeyPathValue {
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for COUNT
|
||||
```
|
||||
let dogsWithPlaymates = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
public func count() -> Where<Root>.Expression<Where<Root>.CollectionTarget, Int> {
|
||||
|
||||
return .init(Root.meta[keyPath: self].cs_keyPathString, "@count")
|
||||
@@ -349,21 +609,45 @@ extension KeyPath where Root: CoreStoreObject, Value: AllowedCoreStoreObjectColl
|
||||
|
||||
extension Where.Expression where D: CoreStoreObject, T == Where<D>.CollectionTarget {
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for COUNT
|
||||
```
|
||||
let dogsWithPlaymates = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets).count() > 1))
|
||||
```
|
||||
*/
|
||||
public func count() -> Where<D>.Expression<T, Int> {
|
||||
|
||||
return .init(self.cs_keyPathString, "@count")
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for ANY
|
||||
```
|
||||
let dogsWithBadNamingSense = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.name).any() > "Spot"))
|
||||
```
|
||||
*/
|
||||
public func any() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("ANY " + self.cs_keyPathString)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for ALL
|
||||
```
|
||||
let allPlaymatePuppies = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.age).all() > 5))
|
||||
```
|
||||
*/
|
||||
public func all() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("ALL " + self.cs_keyPathString)
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a `Where.Expression` clause for NONE
|
||||
```
|
||||
let dogs = CoreStore.fetchAll(From<Dog>().where((\.master ~ \.pets ~ \.name).any() > "Spot"))
|
||||
```
|
||||
*/
|
||||
public func none() -> Where<D>.Expression<T, V> {
|
||||
|
||||
return .init("NONE " + self.cs_keyPathString)
|
||||
|
||||
@@ -29,7 +29,7 @@ import Foundation
|
||||
// MARK: - WhereClauseType
|
||||
|
||||
/**
|
||||
Abstracts the `Where` clause for protocol utilities.
|
||||
Abstracts the `Where` clause for protocol utilities. Typically used only for utility method generic constraints.
|
||||
*/
|
||||
public protocol WhereClauseType: AnyWhereClause {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user