Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for PFQuery.containedBy #1735

Merged
merged 2 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,19 @@
return YES;
}

/**
Matches $containedBy constraints.
*/
+ (BOOL)matchesValue:(NSArray *)values
containedBy:(NSArray *)constraints {
for (id value in values) {
if (![self matchesValue:value containedIn:constraints]) {
return NO;
}
}
return YES;
}

Check warning on line 343 in Parse/Parse/Internal/LocalDataStore/OfflineQueryLogic/PFOfflineQueryLogic.m

View check run for this annotation

Codecov / codecov/patch

Parse/Parse/Internal/LocalDataStore/OfflineQueryLogic/PFOfflineQueryLogic.m#L336-L343

Added lines #L336 - L343 were not covered by tests

/**
Matches $regex constraints.
*/
Expand Down Expand Up @@ -446,6 +459,8 @@
return [self matchesValue:value notContainedIn:constraint];
} else if ([operator isEqualToString:PFQueryKeyContainsAll]) {
return [self matchesValue:value containsAllObjectsInArray:constraint];
} else if ([operator isEqualToString:PFQueryKeyContainedBy]) {
return [self matchesValue:value containedBy:constraint];

Check warning on line 463 in Parse/Parse/Internal/LocalDataStore/OfflineQueryLogic/PFOfflineQueryLogic.m

View check run for this annotation

Codecov / codecov/patch

Parse/Parse/Internal/LocalDataStore/OfflineQueryLogic/PFOfflineQueryLogic.m#L462-L463

Added lines #L462 - L463 were not covered by tests
} else if ([operator isEqualToString:PFQueryKeyRegex]) {
return [self matchesValue:value regex:constraint withOptions:allKeyConstraints[PFQueryOptionKeyRegexOptions]];
} else if ([operator isEqualToString:PFQueryOptionKeyRegexOptions]) {
Expand Down
1 change: 1 addition & 0 deletions Parse/Parse/Internal/Query/PFQueryConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern NSString *const PFQueryKeyGreaterThanOrEqualTo;
extern NSString *const PFQueryKeyContainedIn;
extern NSString *const PFQueryKeyNotContainedIn;
extern NSString *const PFQueryKeyContainsAll;
extern NSString *const PFQueryKeyContainedBy;
extern NSString *const PFQueryKeyNearSphere;
extern NSString *const PFQueryKeyWithin;
extern NSString *const PFQueryKeyGeoWithin;
Expand Down
1 change: 1 addition & 0 deletions Parse/Parse/Internal/Query/PFQueryConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
NSString *const PFQueryKeyContainedIn = @"$in";
NSString *const PFQueryKeyNotContainedIn = @"$nin";
NSString *const PFQueryKeyContainsAll = @"$all";
NSString *const PFQueryKeyContainedBy = @"$containedBy";
NSString *const PFQueryKeyNearSphere = @"$nearSphere";
NSString *const PFQueryKeyWithin = @"$within";
NSString *const PFQueryKeyGeoWithin = @"$geoWithin";
Expand Down
11 changes: 11 additions & 0 deletions Parse/Parse/Source/PFQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,17 @@ typedef void (^PFQueryArrayResultBlock)(NSArray<PFGenericObject> *_Nullable obje
*/
- (instancetype)whereKey:(NSString *)key containsAllObjectsInArray:(NSArray *)array;

/**
Adds a constraint to the query that requires a particular key's value to
be contained by the provided list of values. Get objects where all array elements match
@param key The key to be constrained.
@param array The array of values to search for.
@return The same instance of `PFQuery` as the receiver. This allows method chaining.
*/
- (instancetype)whereKey:(NSString *)key containedBy:(NSArray *)array;

///--------------------------------------
#pragma mark - Adding Location Constraints
///--------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions Parse/Parse/Source/PFQuery.m
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@
return [self whereKey:key condition:PFQueryKeyContainsAll object:array];
}

- (instancetype)whereKey:(NSString *)key containedBy:(NSArray *)inArray {
return [self whereKey:key condition:PFQueryKeyContainedBy object:inArray];
}

Check warning on line 308 in Parse/Parse/Source/PFQuery.m

View check run for this annotation

Codecov / codecov/patch

Parse/Parse/Source/PFQuery.m#L306-L308

Added lines #L306 - L308 were not covered by tests

- (instancetype)whereKey:(NSString *)key nearGeoPoint:(PFGeoPoint *)geopoint {
return [self whereKey:key condition:PFQueryKeyNearSphere object:geopoint];
}
Expand Down
36 changes: 36 additions & 0 deletions Parse/Tests/Unit/OfflineQueryLogicUnitTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,42 @@ - (void)testQueryAll {
[task waitUntilFinished];
}

- (void)testQueryContainedBy {
PFOfflineQueryLogic *logic = [[PFOfflineQueryLogic alloc] init];
PFSQLiteDatabase *database = [[PFSQLiteDatabase alloc] init];

PFObject *object = [PFObject objectWithClassName:@"Object"];
object[@"numbers"] = @[@0, @2];
object[@"letters"] = @[@"b", @"c", @"d"];
PFQuery *query = [PFQuery queryWithClassName:@"Object"];
BFTask *task = [BFTask taskWithResult:nil];

[query whereKey:@"numbers" containedBy:@[@1, @2, @3, @4]];
PFConstraintMatcherBlock matcherBlock = [logic createMatcherForQueryState:query.state user:_user];

// Check matcher
task = [[task continueWithBlock:^id(BFTask *task) {
return matcherBlock(object, database);
}] continueWithBlock:^id(BFTask *task) {
XCTAssertFalse([task.result boolValue]);
return nil;
}];

query = [PFQuery queryWithClassName:@"Object"];
[query whereKey:@"letters" containedBy:@[@"a", @"b", @"c", @"d", @"e"]];
matcherBlock = [logic createMatcherForQueryState:query.state user:_user];

// Check matcher
task = [[task continueWithBlock:^id(BFTask *task) {
return matcherBlock(object, database);
}] continueWithBlock:^id(BFTask *task) {
XCTAssertTrue([task.result boolValue]);
return nil;
}];

[task waitUntilFinished];
}

- (void)testQueryRegex {
PFOfflineQueryLogic *logic = [[PFOfflineQueryLogic alloc] init];
PFSQLiteDatabase *database = [[PFSQLiteDatabase alloc] init];
Expand Down
6 changes: 6 additions & 0 deletions Parse/Tests/Unit/QueryUnitTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ - (void)testWhereContainsAllObjectsInArray {
XCTAssertEqualObjects(query.state.conditions, @{ @"yolo" : @{@"$all" : @[ @"yarr" ]} });
}

- (void)testWhereContainedBy {
PFQuery *query = [PFQuery queryWithClassName:@"a"];
[query whereKey:@"yolo" containedBy:@[ @"yarr" ]];
XCTAssertEqualObjects(query.state.conditions, @{ @"yolo" : @{@"$containedBy" : @[ @"yarr" ]} });
}

- (void)testWhereKeyNearGeoPoint {
PFGeoPoint *geoPoint = [PFGeoPoint geoPointWithLatitude:10.0 longitude:20.0];

Expand Down
Loading