aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/Source/Core/FSTQuery.h
blob: e38d3dde94cf1b66c2280a9c35b789473c65b4dc (plain)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
 * Copyright 2017 Google
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#import <Foundation/Foundation.h>

#include "Firestore/core/src/firebase/firestore/model/field_path.h"
#include "Firestore/core/src/firebase/firestore/model/resource_path.h"

@class FSTDocument;
@class FSTFieldValue;

NS_ASSUME_NONNULL_BEGIN

/**
 * FSTRelationFilterOperator is a value relation operator that can be used to filter documents.
 * It is similar to NSPredicateOperatorType, but only has operators supported by Firestore.
 */
typedef NS_ENUM(NSInteger, FSTRelationFilterOperator) {
  FSTRelationFilterOperatorLessThan = 0,
  FSTRelationFilterOperatorLessThanOrEqual,
  FSTRelationFilterOperatorEqual,
  FSTRelationFilterOperatorGreaterThanOrEqual,
  FSTRelationFilterOperatorGreaterThan,
  FSTRelationFilterOperatorArrayContains,
};

/** Interface used for all query filters. */
@protocol FSTFilter <NSObject>

/** Returns the field the Filter operates over. */
- (const firebase::firestore::model::FieldPath &)field;

/** Returns true if a document matches the filter. */
- (BOOL)matchesDocument:(FSTDocument *)document;

/** A unique ID identifying the filter; used when serializing queries. */
- (NSString *)canonicalID;

@end

/**
 * FSTRelationFilter is a document filter constraint on a query with a single relation operator.
 * It is similar to NSComparisonPredicate, except customized for Firestore semantics.
 */
@interface FSTRelationFilter : NSObject <FSTFilter>

/**
 * Creates a new constraint for filtering documents.
 *
 * @param field A path to a field in the document to filter on. The LHS of the expression.
 * @param filterOperator The binary operator to apply.
 * @param value A constant value to compare @a field to. The RHS of the expression.
 * @return A new instance of FSTRelationFilter.
 */
+ (instancetype)filterWithField:(firebase::firestore::model::FieldPath)field
                 filterOperator:(FSTRelationFilterOperator)filterOperator
                          value:(FSTFieldValue *)value;

- (instancetype)init NS_UNAVAILABLE;

/** Returns YES if the receiver is not an equality relation. */
- (BOOL)isInequality;

/** The left hand side of the relation. A path into a document field. */
- (const firebase::firestore::model::FieldPath &)field;

/** The type of equality/inequality operator to use in the relation. */
@property(nonatomic, assign, readonly) FSTRelationFilterOperator filterOperator;

/** The right hand side of the relation. A constant value to compare to. */
@property(nonatomic, strong, readonly) FSTFieldValue *value;

@end

/** Filter that matches NULL values. */
@interface FSTNullFilter : NSObject <FSTFilter>
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithField:(firebase::firestore::model::FieldPath)field
    NS_DESIGNATED_INITIALIZER;
@end

/** Filter that matches NAN values. */
@interface FSTNanFilter : NSObject <FSTFilter>
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithField:(firebase::firestore::model::FieldPath)field
    NS_DESIGNATED_INITIALIZER;
@end

/** FSTSortOrder is a field and direction to order query results by. */
@interface FSTSortOrder : NSObject <NSCopying>

/** Creates a new sort order with the given field and direction. */
+ (instancetype)sortOrderWithFieldPath:(firebase::firestore::model::FieldPath)fieldPath
                             ascending:(BOOL)ascending;

- (instancetype)init NS_UNAVAILABLE;

/** Compares two documents based on the field and direction of this sort order. */
- (NSComparisonResult)compareDocument:(FSTDocument *)document1 toDocument:(FSTDocument *)document2;

/** The field to sort by. */
- (const firebase::firestore::model::FieldPath &)field;

/** The direction of the sort. */
@property(nonatomic, assign, readonly, getter=isAscending) BOOL ascending;

@end

/**
 * FSTBound represents a bound of a query.
 *
 * The bound is specified with the given components representing a position and whether it's just
 * before or just after the position (relative to whatever the query order is).
 *
 * The position represents a logical index position for a query. It's a prefix of values for
 * the (potentially implicit) order by clauses of a query.
 *
 * FSTBound provides a function to determine whether a document comes before or after a bound.
 * This is influenced by whether the position is just before or just after the provided values.
 */
@interface FSTBound : NSObject <NSCopying>

/**
 * Creates a new bound.
 *
 * @param position The position relative to the sort order.
 * @param isBefore Whether this bound is just before or just after the position.
 */
+ (instancetype)boundWithPosition:(NSArray<FSTFieldValue *> *)position isBefore:(BOOL)isBefore;

/** Whether this bound is just before or just after the provided position */
@property(nonatomic, assign, readonly, getter=isBefore) BOOL before;

/** The index position of this bound represented as an array of field values. */
@property(nonatomic, strong, readonly) NSArray<FSTFieldValue *> *position;

/** Returns YES if a document comes before a bound using the provided sort order. */
- (BOOL)sortsBeforeDocument:(FSTDocument *)document
             usingSortOrder:(NSArray<FSTSortOrder *> *)sortOrder;

@end

/** FSTQuery represents the internal structure of a Firestore query. */
@interface FSTQuery : NSObject <NSCopying>

- (id)init NS_UNAVAILABLE;

/**
 * Initializes a query with all of its components directly.
 */
- (instancetype)initWithPath:(firebase::firestore::model::ResourcePath)path
                    filterBy:(NSArray<id<FSTFilter>> *)filters
                     orderBy:(NSArray<FSTSortOrder *> *)sortOrders
                       limit:(NSInteger)limit
                     startAt:(nullable FSTBound *)startAtBound
                       endAt:(nullable FSTBound *)endAtBound NS_DESIGNATED_INITIALIZER;

/**
 * Creates and returns a new FSTQuery.
 *
 * @param path The path to the collection to be queried over.
 * @return A new instance of FSTQuery.
 */
+ (instancetype)queryWithPath:(firebase::firestore::model::ResourcePath)path;

/**
 * Returns the list of ordering constraints that were explicitly requested on the query by the
 * user.
 *
 * Note that the actual query performed might add additional sort orders to match the behavior
 * of the backend.
 */
- (NSArray<FSTSortOrder *> *)explicitSortOrders;

/**
 * Returns the full list of ordering constraints on the query.
 *
 * This might include additional sort orders added implicitly to match the backend behavior.
 */
- (NSArray<FSTSortOrder *> *)sortOrders;

/**
 * Creates a new FSTQuery with an additional filter.
 *
 * @param filter The predicate to filter by.
 * @return the new FSTQuery.
 */
- (instancetype)queryByAddingFilter:(id<FSTFilter>)filter;

/**
 * Creates a new FSTQuery with an additional ordering constraint.
 *
 * @param sortOrder The key and direction to order by.
 * @return the new FSTQuery.
 */
- (instancetype)queryByAddingSortOrder:(FSTSortOrder *)sortOrder;

/**
 * Returns a new FSTQuery with the given limit on how many results can be returned.
 *
 * @param limit The maximum number of results to return. If @a limit <= 0, behavior is unspecified.
 *     If @a limit == NSNotFound, then no limit is applied.
 */
- (instancetype)queryBySettingLimit:(NSInteger)limit;

/**
 * Creates a new FSTQuery starting at the provided bound.
 *
 * @param bound The bound to start this query at.
 * @return the new FSTQuery.
 */
- (instancetype)queryByAddingStartAt:(FSTBound *)bound;

/**
 * Creates a new FSTQuery ending at the provided bound.
 *
 * @param bound The bound to end this query at.
 * @return the new FSTQuery.
 */
- (instancetype)queryByAddingEndAt:(FSTBound *)bound;

/** Returns YES if the receiver is query for a specific document. */
- (BOOL)isDocumentQuery;

/** Returns YES if the @a document matches the constraints of the receiver. */
- (BOOL)matchesDocument:(FSTDocument *)document;

/** Returns a comparator that will sort documents according to the receiver's sort order. */
- (NSComparator)comparator;

/** Returns the field of the first filter on the receiver that's an inequality, or nullptr if none.
 */
- (const firebase::firestore::model::FieldPath *)inequalityFilterField;

/** Returns YES if the query has an arrayContains filter already. */
- (BOOL)hasArrayContainsFilter;

/** Returns the first field in an order-by constraint, or nullptr if none. */
- (const firebase::firestore::model::FieldPath *)firstSortOrderField;

/** The base path of the query. */
- (const firebase::firestore::model::ResourcePath &)path;

/** The filters on the documents returned by the query. */
@property(nonatomic, strong, readonly) NSArray<id<FSTFilter>> *filters;

/** The maximum number of results to return, or NSNotFound if no limit. */
@property(nonatomic, assign, readonly) NSInteger limit;

/**
 * A canonical string identifying the query. Two different instances of equivalent queries will
 * return the same canonicalID.
 */
@property(nonatomic, strong, readonly) NSString *canonicalID;

/** An optional bound to start the query at. */
@property(nonatomic, nullable, strong, readonly) FSTBound *startAt;

/** An optional bound to end the query at. */
@property(nonatomic, nullable, strong, readonly) FSTBound *endAt;

@end

NS_ASSUME_NONNULL_END