@@ -587,6 +587,31 @@ - (PFConstraintMatcherBlock)createOrMatcherForQueries:(NSArray *)queries user:(P
587587 };
588588}
589589
590+ /* *
591+ Handles $and queries.
592+ */
593+ - (PFConstraintMatcherBlock)createAndMatcherForQueries : (NSArray *)queries user : (PFUser *)user {
594+ NSMutableArray *matchers = [NSMutableArray array ];
595+ for (PFQuery *query in queries) {
596+ PFConstraintMatcherBlock matcher = [self createMatcherWithQueryConstraints: query.state.conditions user: user];
597+ [matchers addObject: matcher];
598+ }
599+
600+ // Now AND together the constraints for each query.
601+ return ^BFTask *(PFObject *object, PFSQLiteDatabase *database) {
602+ BFTask *task = [BFTask taskWithResult: @YES ];
603+ for (PFConstraintMatcherBlock matcher in matchers) {
604+ task = [task continueWithSuccessBlock: ^id (BFTask *task) {
605+ if (![task.result boolValue ]) {
606+ return task;
607+ }
608+ return matcher (object, database);
609+ }];
610+ }
611+ return task;
612+ };
613+ }
614+
590615/* *
591616 Returns a PFConstraintMatcherBlock that return true iff the object matches queryConstraints. This
592617 takes in a SQLiteDatabase connection because SQLite is finicky about nesting connections, so we
@@ -599,6 +624,10 @@ - (PFConstraintMatcherBlock)createMatcherWithQueryConstraints:(NSDictionary *)qu
599624 // A set of queries to be OR-ed together
600625 PFConstraintMatcherBlock matcher = [self createOrMatcherForQueries: queryConstraintValue user: user];
601626 [matchers addObject: matcher];
627+ } else if ([key isEqualToString: PFQueryKeyAnd]) {
628+ // A set of queries to be AND-ed together
629+ PFConstraintMatcherBlock matcher = [self createAndMatcherForQueries: queryConstraintValue user: user];
630+ [matchers addObject: matcher];
602631 } else if ([key isEqualToString: PFQueryKeyRelatedTo]) {
603632 PFConstraintMatcherBlock matcher = ^BFTask *(PFObject *object, PFSQLiteDatabase *database) {
604633 PFObject *parent = queryConstraintValue[PFQueryKeyObject];
0 commit comments