FSTQuery.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <Foundation/Foundation.h>
  17. #include <vector>
  18. #include "Firestore/core/src/firebase/firestore/core/filter.h"
  19. #include "Firestore/core/src/firebase/firestore/model/document_set.h"
  20. #include "Firestore/core/src/firebase/firestore/model/field_path.h"
  21. #include "Firestore/core/src/firebase/firestore/model/field_value.h"
  22. #include "Firestore/core/src/firebase/firestore/model/resource_path.h"
  23. @class FSTDocument;
  24. namespace core = firebase::firestore::core;
  25. namespace model = firebase::firestore::model;
  26. namespace util = firebase::firestore::util;
  27. NS_ASSUME_NONNULL_BEGIN
  28. /** Interface used for all query filters. */
  29. @interface FSTFilter : NSObject
  30. /**
  31. * Creates a filter for the provided path, operator, and value.
  32. *
  33. * Note that if the relational operator is Filter::Operator::Equal and the
  34. * value is FieldValue::Null() or FieldValue::Nan(), this will return the
  35. * appropriate FSTNullFilter or FSTNanFilter class instead of a
  36. * FSTRelationFilter.
  37. */
  38. + (instancetype)filterWithField:(const model::FieldPath &)field
  39. filterOperator:(core::Filter::Operator)op
  40. value:(model::FieldValue)value;
  41. /** Returns the field the Filter operates over. Abstract method. */
  42. - (const model::FieldPath &)field;
  43. /** Returns true if a document matches the filter. Abstract method. */
  44. - (BOOL)matchesDocument:(FSTDocument *)document;
  45. /** A unique ID identifying the filter; used when serializing queries. Abstract method. */
  46. - (NSString *)canonicalID;
  47. @end
  48. /**
  49. * FSTRelationFilter is a document filter constraint on a query with a single relation operator.
  50. * It is similar to NSComparisonPredicate, except customized for Firestore semantics.
  51. */
  52. @interface FSTRelationFilter : FSTFilter
  53. /**
  54. * Creates a new constraint for filtering documents.
  55. *
  56. * @param field A path to a field in the document to filter on. The LHS of the expression.
  57. * @param filterOperator The binary operator to apply.
  58. * @param value A constant value to compare @a field to. The RHS of the expression.
  59. * @return A new instance of FSTRelationFilter.
  60. */
  61. - (instancetype)initWithField:(model::FieldPath)field
  62. filterOperator:(core::Filter::Operator)filterOperator
  63. value:(model::FieldValue)value;
  64. - (instancetype)init NS_UNAVAILABLE;
  65. /** Returns YES if the receiver is not an equality relation. */
  66. - (BOOL)isInequality;
  67. /** The left hand side of the relation. A path into a document field. */
  68. - (const model::FieldPath &)field;
  69. /** The type of equality/inequality operator to use in the relation. */
  70. @property(nonatomic, assign, readonly) core::Filter::Operator filterOperator;
  71. /** The right hand side of the relation. A constant value to compare to. */
  72. @property(nonatomic, assign, readonly) const model::FieldValue &value;
  73. @end
  74. /** Filter that matches NULL values. */
  75. @interface FSTNullFilter : FSTFilter
  76. - (instancetype)init NS_UNAVAILABLE;
  77. - (instancetype)initWithField:(model::FieldPath)field NS_DESIGNATED_INITIALIZER;
  78. @end
  79. /** Filter that matches NAN values. */
  80. @interface FSTNanFilter : FSTFilter
  81. - (instancetype)init NS_UNAVAILABLE;
  82. - (instancetype)initWithField:(model::FieldPath)field NS_DESIGNATED_INITIALIZER;
  83. @end
  84. /** FSTSortOrder is a field and direction to order query results by. */
  85. @interface FSTSortOrder : NSObject <NSCopying>
  86. /** Creates a new sort order with the given field and direction. */
  87. + (instancetype)sortOrderWithFieldPath:(model::FieldPath)fieldPath ascending:(BOOL)ascending;
  88. - (instancetype)init NS_UNAVAILABLE;
  89. /** Compares two documents based on the field and direction of this sort order. */
  90. - (util::ComparisonResult)compareDocument:(FSTDocument *)document1
  91. toDocument:(FSTDocument *)document2;
  92. /** The field to sort by. */
  93. - (const model::FieldPath &)field;
  94. /** The direction of the sort. */
  95. @property(nonatomic, assign, readonly, getter=isAscending) BOOL ascending;
  96. @end
  97. /**
  98. * FSTBound represents a bound of a query.
  99. *
  100. * The bound is specified with the given components representing a position and whether it's just
  101. * before or just after the position (relative to whatever the query order is).
  102. *
  103. * The position represents a logical index position for a query. It's a prefix of values for
  104. * the (potentially implicit) order by clauses of a query.
  105. *
  106. * FSTBound provides a function to determine whether a document comes before or after a bound.
  107. * This is influenced by whether the position is just before or just after the provided values.
  108. */
  109. @interface FSTBound : NSObject <NSCopying>
  110. /**
  111. * Creates a new bound.
  112. *
  113. * @param position The position relative to the sort order.
  114. * @param isBefore Whether this bound is just before or just after the position.
  115. */
  116. + (instancetype)boundWithPosition:(std::vector<model::FieldValue>)position isBefore:(bool)isBefore;
  117. /** Whether this bound is just before or just after the provided position */
  118. @property(nonatomic, assign, readonly, getter=isBefore) bool before;
  119. /** The index position of this bound represented as an array of field values. */
  120. @property(nonatomic, assign, readonly) const std::vector<model::FieldValue> &position;
  121. /** Returns true if a document comes before a bound using the provided sort order. */
  122. - (bool)sortsBeforeDocument:(FSTDocument *)document
  123. usingSortOrder:(NSArray<FSTSortOrder *> *)sortOrder;
  124. @end
  125. /** FSTQuery represents the internal structure of a Firestore query. */
  126. @interface FSTQuery : NSObject <NSCopying>
  127. - (id)init NS_UNAVAILABLE;
  128. /**
  129. * Initializes a query with all of its components directly.
  130. */
  131. - (instancetype)initWithPath:(model::ResourcePath)path
  132. collectionGroup:(nullable NSString *)collectionGroup
  133. filterBy:(NSArray<FSTFilter *> *)filters
  134. orderBy:(NSArray<FSTSortOrder *> *)sortOrders
  135. limit:(int32_t)limit
  136. startAt:(nullable FSTBound *)startAtBound
  137. endAt:(nullable FSTBound *)endAtBound NS_DESIGNATED_INITIALIZER;
  138. /**
  139. * Creates and returns a new FSTQuery.
  140. *
  141. * @param path The path to the collection to be queried over.
  142. * @return A new instance of FSTQuery.
  143. */
  144. + (instancetype)queryWithPath:(model::ResourcePath)path;
  145. /**
  146. * Creates and returns a new FSTQuery.
  147. *
  148. * @param path The path to the location to be queried over. Must currently be
  149. * empty in the case of a collection group query.
  150. * @param collectionGroup The collection group to be queried over. nil if this
  151. * is not a collection group query.
  152. * @return A new instance of FSTQuery.
  153. */
  154. + (instancetype)queryWithPath:(model::ResourcePath)path
  155. collectionGroup:(nullable NSString *)collectionGroup;
  156. /**
  157. * Returns the list of ordering constraints that were explicitly requested on the query by the
  158. * user.
  159. *
  160. * Note that the actual query performed might add additional sort orders to match the behavior
  161. * of the backend.
  162. */
  163. - (NSArray<FSTSortOrder *> *)explicitSortOrders;
  164. /**
  165. * Returns the full list of ordering constraints on the query.
  166. *
  167. * This might include additional sort orders added implicitly to match the backend behavior.
  168. */
  169. - (NSArray<FSTSortOrder *> *)sortOrders;
  170. /**
  171. * Creates a new FSTQuery with an additional filter.
  172. *
  173. * @param filter The predicate to filter by.
  174. * @return the new FSTQuery.
  175. */
  176. - (instancetype)queryByAddingFilter:(FSTFilter *)filter;
  177. /**
  178. * Creates a new FSTQuery with an additional ordering constraint.
  179. *
  180. * @param sortOrder The key and direction to order by.
  181. * @return the new FSTQuery.
  182. */
  183. - (instancetype)queryByAddingSortOrder:(FSTSortOrder *)sortOrder;
  184. /**
  185. * Returns a new FSTQuery with the given limit on how many results can be returned.
  186. *
  187. * @param limit The maximum number of results to return. If @a limit <= 0, behavior is unspecified.
  188. * If @a limit == NSNotFound, then no limit is applied.
  189. */
  190. - (instancetype)queryBySettingLimit:(int32_t)limit;
  191. /**
  192. * Creates a new FSTQuery starting at the provided bound.
  193. *
  194. * @param bound The bound to start this query at.
  195. * @return the new FSTQuery.
  196. */
  197. - (instancetype)queryByAddingStartAt:(FSTBound *)bound;
  198. /**
  199. * Creates a new FSTQuery ending at the provided bound.
  200. *
  201. * @param bound The bound to end this query at.
  202. * @return the new FSTQuery.
  203. */
  204. - (instancetype)queryByAddingEndAt:(FSTBound *)bound;
  205. /**
  206. * Helper to convert a collection group query into a collection query at a specific path. This is
  207. * used when executing collection group queries, since we have to split the query into a set of
  208. * collection queries at multiple paths.
  209. */
  210. - (instancetype)collectionQueryAtPath:(model::ResourcePath)path;
  211. /** Returns YES if the receiver is query for a specific document. */
  212. - (BOOL)isDocumentQuery;
  213. /** Returns YES if the receiver is a collection group query. */
  214. - (BOOL)isCollectionGroupQuery;
  215. /** Returns YES if the @a document matches the constraints of the receiver. */
  216. - (BOOL)matchesDocument:(FSTDocument *)document;
  217. /** Returns a comparator that will sort documents according to the receiver's sort order. */
  218. - (model::DocumentComparator)comparator;
  219. /** Returns the field of the first filter on the receiver that's an inequality, or nullptr if none.
  220. */
  221. - (nullable const model::FieldPath *)inequalityFilterField;
  222. /** Returns YES if the query has an arrayContains filter already. */
  223. - (BOOL)hasArrayContainsFilter;
  224. /** Returns the first field in an order-by constraint, or nullptr if none. */
  225. - (nullable const model::FieldPath *)firstSortOrderField;
  226. /** The base path of the query. */
  227. - (const model::ResourcePath &)path;
  228. /** The collection group of the query. */
  229. @property(nonatomic, nullable, strong, readonly) NSString *collectionGroup;
  230. /** The filters on the documents returned by the query. */
  231. @property(nonatomic, strong, readonly) NSArray<FSTFilter *> *filters;
  232. /** The maximum number of results to return, or NSNotFound if no limit. */
  233. @property(nonatomic, assign, readonly) int32_t limit;
  234. /**
  235. * A canonical string identifying the query. Two different instances of equivalent queries will
  236. * return the same canonicalID.
  237. */
  238. @property(nonatomic, strong, readonly) NSString *canonicalID;
  239. /** An optional bound to start the query at. */
  240. @property(nonatomic, nullable, strong, readonly) FSTBound *startAt;
  241. /** An optional bound to end the query at. */
  242. @property(nonatomic, nullable, strong, readonly) FSTBound *endAt;
  243. @end
  244. NS_ASSUME_NONNULL_END