-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathQuery.swift
101 lines (90 loc) · 3.27 KB
/
Query.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import Foundation
import Schemata
/// A value representing a query of a model type.
public struct Query<Key: ModelValue, Model: PersistDB.Model>: Hashable {
/// The predicates used to filter results.
public var predicates: [Predicate<Model>]
/// The orderings used to order results.
///
/// - note: Results are sorted by the first ordering first. Subsequent ordering are used
/// to break ties.
public var order: [Ordering<Model>]
/// The grouping that's used by this query.
public var groupedBy: Grouping<Model, Key>
public init(
predicates: [Predicate<Model>],
order: [Ordering<Model>],
groupedBy: Grouping<Model, Key>
) {
self.predicates = predicates
self.order = order
self.groupedBy = groupedBy
}
}
extension Query where Key == None {
/// Creates a query that returns all instances of `Model` in the store.
public init() {
predicates = []
order = []
groupedBy = .none
}
}
extension Query {
/// Returns a query that is filtered by the given predicate.
public func filter(_ predicate: Predicate<Model>) -> Query {
var result = self
result.predicates.append(predicate)
return result
}
/// Returns a query that is grouped by the given keypath.
public func group<Value>(
by keyPath: KeyPath<Model, Value>,
ascending: Bool = true
) -> Query<Value, Model> {
return group(by: Expression(AnyExpression(keyPath)), ascending: ascending)
}
/// Returns a query that is grouped by the given expression.
public func group<Value>(
by expression: Expression<Model, Value>,
ascending: Bool = true
) -> Query<Value, Model> {
return Query<Value, Model>(
predicates: predicates,
order: order,
groupedBy: Grouping(expression, ascending: ascending)
)
}
/// Returns a query that is sorted by the given keypath.
///
/// - important: Orderings are inserted into the beginning of the array.
/// `.sort(by: \.a, ascending: true).sort(by: \.b, ascending: true)` will sort by
/// `b` and use `a` to break ties.
public func sort<Value>(by keyPath: KeyPath<Model, Value>, ascending: Bool = true) -> Query {
var result = self
let descriptor = Ordering(keyPath, ascending: ascending)
result.order.insert(descriptor, at: 0)
return result
}
/// Returns a query that is sorted by the given expression.
///
/// - important: Orderings are inserted into the beginning of the array.
/// `.sort(by: \.a, ascending: true).sort(by: \.b, ascending: true)` will sort by
/// `b` and use `a` to break ties.
public func sort<Value>(
by expression: Expression<Model, Value>,
ascending: Bool = true
) -> Query {
var result = self
let descriptor = Ordering<Model>(expression.expression, ascending: ascending)
result.order.insert(descriptor, at: 0)
return result
}
}
extension Query {
public var count: Aggregate<Model, Int> {
return Aggregate(
expression: .function(.count, [ AnyExpression(Model.idKeyPath) ]),
predicates: predicates
)
}
}