Skip to content

Commit

Permalink
feat: Add support to exclude PFObject fields in query results with …
Browse files Browse the repository at this point in the history
…`PFQuery.excludeKeys` (#1731)
  • Loading branch information
dplewis authored Jul 11, 2023
1 parent 19c8a62 commit 98e5faf
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Parse/Parse/Internal/Commands/PFRESTQueryCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
conditions:(nullable NSDictionary *)conditions
selectedKeys:(nullable NSSet *)selectedKeys
includedKeys:(nullable NSSet *)includedKeys
excludedKeys:(nullable NSSet *)excludedKeys
limit:(NSInteger)limit
skip:(NSInteger)skip
explain:(BOOL)explain
Expand All @@ -54,6 +55,7 @@ NS_ASSUME_NONNULL_BEGIN
conditions:(nullable NSDictionary *)conditions
selectedKeys:(nullable NSSet *)selectedKeys
includedKeys:(nullable NSSet *)includedKeys
excludedKeys:(nullable NSSet *)excludedKeys
limit:(NSInteger)limit
skip:(NSInteger)skip
explain:(BOOL)explain
Expand Down
12 changes: 12 additions & 0 deletions Parse/Parse/Internal/Commands/PFRESTQueryCommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ + (nullable instancetype)findCommandForClassWithName:(NSString *)className
conditions:(NSDictionary *)conditions
selectedKeys:(NSSet *)selectedKeys
includedKeys:(NSSet *)includedKeys
excludedKeys:(NSSet *)excludedKeys
limit:(NSInteger)limit
skip:(NSInteger)skip
explain:(BOOL)explain
Expand All @@ -48,6 +49,7 @@ + (nullable instancetype)findCommandForClassWithName:(NSString *)className
conditions:conditions
selectedKeys:selectedKeys
includedKeys:includedKeys
excludedKeys:excludedKeys
limit:limit
skip:skip
explain:explain
Expand Down Expand Up @@ -102,6 +104,7 @@ + (nullable NSDictionary *)findCommandParametersForQueryState:(PFQueryState *)qu
conditions:queryState.conditions
selectedKeys:queryState.selectedKeys
includedKeys:queryState.includedKeys
excludedKeys:queryState.excludedKeys
limit:queryState.limit
skip:queryState.skip
explain:queryState.explain
Expand All @@ -115,6 +118,7 @@ + (nullable NSDictionary *)findCommandParametersWithOrder:(NSString *)order
conditions:(NSDictionary *)conditions
selectedKeys:(NSSet *)selectedKeys
includedKeys:(NSSet *)includedKeys
excludedKeys:(NSSet *)excludedKeys
limit:(NSInteger)limit
skip:(NSInteger)skip
explain:(BOOL)explain
Expand All @@ -137,6 +141,11 @@ + (nullable NSDictionary *)findCommandParametersWithOrder:(NSString *)order
NSArray *keysArray = [includedKeys sortedArrayUsingDescriptors:sortDescriptors];
parameters[@"include"] = [keysArray componentsJoinedByString:@","];
}
if (excludedKeys.count > 0) {
NSArray *sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES selector:@selector(compare:)] ];
NSArray *keysArray = [excludedKeys sortedArrayUsingDescriptors:sortDescriptors];
parameters[@"excludedKeys"] = [keysArray componentsJoinedByString:@","];
}
if (limit >= 0) {
parameters[@"limit"] = [NSString stringWithFormat:@"%d", (int)limit];
}
Expand Down Expand Up @@ -171,12 +180,14 @@ + (nullable NSDictionary *)findCommandParametersWithOrder:(NSString *)order
PFParameterAssert(subquery.state.skip == 0, @"OR queries do not support sub queries with skip");
PFParameterAssert(subquery.state.sortKeys.count == 0, @"OR queries do not support sub queries with order");
PFParameterAssert(subquery.state.includedKeys.count == 0, @"OR queries do not support sub-queries with includes");
PFParameterAssert(subquery.state.excludedKeys.count == 0, @"OR queries do not support sub-queries with excludeKeys");
PFParameterAssert(subquery.state.selectedKeys == nil, @"OR queries do not support sub-queries with selectKeys");

NSDictionary *queryDict = [self findCommandParametersWithOrder:subquery.state.sortOrderString
conditions:subquery.state.conditions
selectedKeys:subquery.state.selectedKeys
includedKeys:subquery.state.includedKeys
excludedKeys:subquery.state.excludedKeys
limit:subquery.state.limit
skip:subquery.state.skip
explain:subquery.state.explain
Expand Down Expand Up @@ -240,6 +251,7 @@ + (nullable id)_encodeSubqueryIfNeeded:(id)object error:(NSError * __autoreleasi
conditions:subquery.state.conditions
selectedKeys:subquery.state.selectedKeys
includedKeys:subquery.state.includedKeys
excludedKeys:subquery.state.excludedKeys
limit:subquery.state.limit
skip:subquery.state.skip
explain:subquery.state.explain
Expand Down
7 changes: 7 additions & 0 deletions Parse/Parse/Internal/Query/State/PFMutableQueryState.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@
- (void)includeKey:(NSString *)key;
- (void)includeKeys:(NSArray<NSString *> *)keys;

///--------------------------------------
#pragma mark - Excludes
///--------------------------------------

- (void)excludeKey:(NSString *)key;
- (void)excludeKeys:(NSArray<NSString *> *)keys;

///--------------------------------------
#pragma mark - Selected Keys
///--------------------------------------
Expand Down
23 changes: 23 additions & 0 deletions Parse/Parse/Internal/Query/State/PFMutableQueryState.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ @interface PFMutableQueryState () {
NSMutableDictionary<NSString *, id> *_conditions;
NSMutableArray<NSString *> *_sortKeys;
NSMutableSet<NSString *> *_includedKeys;
NSMutableSet<NSString *> *_excludedKeys;
NSMutableDictionary<NSString *, NSString *> *_extraOptions;
}

Expand All @@ -27,6 +28,7 @@ @implementation PFMutableQueryState
@synthesize conditions = _conditions;
@synthesize sortKeys = _sortKeys;
@synthesize includedKeys = _includedKeys;
@synthesize excludedKeys = _excludedKeys;
@synthesize extraOptions = _extraOptions;

@dynamic parseClassName;
Expand All @@ -53,6 +55,7 @@ + (NSDictionary *)propertyAttributes {
attributes[PFQueryStatePropertyName(conditions)] = [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeMutableCopy];
attributes[PFQueryStatePropertyName(sortKeys)] = [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeMutableCopy];
attributes[PFQueryStatePropertyName(includedKeys)] = [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeMutableCopy];
attributes[PFQueryStatePropertyName(excludedKeys)] = [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeMutableCopy];
attributes[PFQueryStatePropertyName(extraOptions)] = [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeMutableCopy];

return attributes;
Expand Down Expand Up @@ -163,6 +166,26 @@ - (void)includeKeys:(NSArray<NSString *> *)keys {
}
}

///--------------------------------------
#pragma mark - Excludes
///--------------------------------------

- (void)excludeKey:(NSString *)key {
if (!_excludedKeys) {
_excludedKeys = [NSMutableSet setWithObject:key];
} else {
[_excludedKeys addObject:key];
}
}

- (void)excludeKeys:(NSArray<NSString *> *)keys {
if (!_excludedKeys) {
_excludedKeys = [NSMutableSet setWithArray:keys];
} else {
[_excludedKeys addObjectsFromArray:keys];
}
}

///--------------------------------------
#pragma mark - Selected Keys
///--------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Parse/Parse/Internal/Query/State/PFQueryState.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@property (nonatomic, copy, readonly) NSString *sortOrderString;

@property (nonatomic, copy, readonly) NSSet<NSString *> *includedKeys;
@property (nonatomic, copy, readonly) NSSet<NSString *> *excludedKeys;
@property (nonatomic, copy, readonly) NSSet<NSString *> *selectedKeys;
@property (nonatomic, copy, readonly) NSDictionary<NSString *, NSString *> *extraOptions;

Expand Down
1 change: 1 addition & 0 deletions Parse/Parse/Internal/Query/State/PFQueryState.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ + (NSDictionary *)propertyAttributes {
PFQueryStatePropertyName(conditions): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],
PFQueryStatePropertyName(sortKeys): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],
PFQueryStatePropertyName(includedKeys): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],
PFQueryStatePropertyName(excludedKeys): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],
PFQueryStatePropertyName(selectedKeys): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],
PFQueryStatePropertyName(extraOptions): [PFPropertyAttributes attributesWithAssociationType:PFPropertyInfoAssociationTypeCopy],

Expand Down
1 change: 1 addition & 0 deletions Parse/Parse/Internal/Query/State/PFQueryState_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
NSArray<NSString *> *_sortKeys;

NSSet<NSString *> *_includedKeys;
NSSet<NSString *> *_excludedKeys;
NSSet<NSString *> *_selectedKeys;
NSDictionary<NSString *, NSString *> *_extraOptions;

Expand Down
22 changes: 22 additions & 0 deletions Parse/Parse/Source/PFQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,28 @@ typedef void (^PFQueryArrayResultBlock)(NSArray<PFGenericObject> *_Nullable obje
*/
- (instancetype)includeKeys:(NSArray<NSString *> *)keys;

/**
Make the query restrict the fields of the returned `PFObject`s to exclude the provided key.
If this is called multiple times, then all of the keys specified in each of the calls will be excluded.
@param key The key to exclude in the result.
@return The same instance of `PFQuery` as the receiver. This allows method chaining.
*/
- (instancetype)excludeKey:(NSString *)key;

/**
Make the query restrict the fields of the returned `PFObject`s to exclude the provided keys.
If this is called multiple times, then all of the keys specified in each of the calls will be excluded.
@param keys The keys to exclude in the result.
@return The same instance of `PFQuery` as the receiver. This allows method chaining.
*/
- (instancetype)excludeKeys:(NSArray<NSString *> *)keys;

/**
Make the query restrict the fields of the returned `PFObject`s to include only the provided keys.
Expand Down
16 changes: 16 additions & 0 deletions Parse/Parse/Source/PFQuery.m
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,22 @@ - (instancetype)includeKeys:(NSArray<NSString *> *)keys {
return self;
}

///--------------------------------------
#pragma mark - Exclude
///--------------------------------------

- (instancetype)excludeKey:(NSString *)key {
[self checkIfCommandIsRunning];
[self.state excludeKey:key];
return self;
}

- (instancetype)excludeKeys:(NSArray<NSString *> *)keys {
[self checkIfCommandIsRunning];
[self.state excludeKeys:keys];
return self;
}

///--------------------------------------
#pragma mark - Select
///--------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion Parse/Tests/Other/TestCases/UnitTestCase/PFUnitTestCase.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ - (void)setUp {

[Parse setApplicationId:self.applicationId clientKey:self.clientKey];

[self waitForExpectations:@[expect] timeout:10];
[self waitForExpectations:@[expect] timeout:30];
}

- (void)tearDown {
Expand Down
19 changes: 19 additions & 0 deletions Parse/Tests/Unit/QueryStateUnitTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ - (PFQueryState *)sampleQueryState {
[state sortByKey:@"a" ascending:NO];

[state includeKey:@"yolo"];
[state excludeKey:@"yolo"];
[state selectKeys:@[ @"yolo" ]];
[state redirectClassNameForKey:@"ABC"];
return state;
Expand All @@ -62,6 +63,7 @@ - (void)assertQueryState:(PFQueryState *)state equalToState:(PFQueryState *)diff
XCTAssertEqualObjects(state.sortKeys, differentState.sortKeys);
XCTAssertEqualObjects(state.sortOrderString, differentState.sortOrderString);
XCTAssertEqualObjects(state.includedKeys, differentState.includedKeys);
XCTAssertEqualObjects(state.excludedKeys, differentState.excludedKeys);
XCTAssertEqualObjects(state.selectedKeys, differentState.selectedKeys);
XCTAssertEqualObjects(state.extraOptions, differentState.extraOptions);

Expand Down Expand Up @@ -213,6 +215,23 @@ - (void)testIncludeMultipleKeys {
XCTAssertEqualObjects(state.includedKeys, includedKeys);
}

- (void)testExcludeKeys {
PFMutableQueryState *state = [[PFMutableQueryState alloc] initWithParseClassName:@"Yarr"];
[state excludeKey:@"a"];
[state excludeKey:@"b"];

NSSet *excludedKeys = PF_SET(@"a", @"b");
XCTAssertEqualObjects(state.excludedKeys, excludedKeys);
}

- (void)testExcludeMultipleKeys {
PFMutableQueryState *state = [[PFMutableQueryState alloc] initWithParseClassName:@"Yarr"];
[state excludeKeys:@[ @"a", @"b", @"c" ]];

NSSet *excludedKeys = PF_SET(@"a", @"b", @"c");
XCTAssertEqualObjects(state.excludedKeys, excludedKeys);
}

- (void)testSelectKeys {
PFMutableQueryState *state = [[PFMutableQueryState alloc] initWithParseClassName:@"Yarr"];

Expand Down
13 changes: 13 additions & 0 deletions Parse/Tests/Unit/QueryUnitTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ - (void)testIncludeKey {
XCTAssertTrue([query.state.includedKeys containsObject:@"yolo1"]);
}

- (void)testExcludeKey {
PFQuery *query = [PFQuery queryWithClassName:@"a"];
[query excludeKey:@"yolo"];
XCTAssertEqualObjects(query.state.excludedKeys, (PF_SET(@"yolo")));

[query excludeKey:@"yolo1"];
XCTAssertEqualObjects(query.state.excludedKeys, (PF_SET(@"yolo", @"yolo1")));
XCTAssertTrue([query.state.excludedKeys containsObject:@"yolo"]);
XCTAssertTrue([query.state.excludedKeys containsObject:@"yolo1"]);
}

- (void)testSelectKeys {
PFQuery *query = [PFQuery queryWithClassName:@"a"];
[query selectKeys:@[ @"a", @"a" ]];
Expand Down Expand Up @@ -1320,6 +1331,7 @@ - (void)testNSCopying {
[query orderByAscending:@"b"];
[query includeKey:@"c"];
[query selectKeys:@[ @"d" ]];
[query excludeKeys:@[ @"f" ]];
[query redirectClassNameForKey:@"e"];

query.limit = 10;
Expand All @@ -1338,6 +1350,7 @@ - (void)testNSCopying {
XCTAssertEqualObjects(queryCopy.state.conditions[@"a"], query.state.conditions[@"a"]);
XCTAssertEqualObjects(queryCopy.state.sortOrderString, query.state.sortOrderString);
XCTAssertEqualObjects([queryCopy.state.includedKeys anyObject], [query.state.includedKeys anyObject]);
XCTAssertEqualObjects([queryCopy.state.excludedKeys anyObject], [query.state.excludedKeys anyObject]);
XCTAssertEqualObjects([queryCopy.state.selectedKeys anyObject], [query.state.selectedKeys anyObject]);
XCTAssertEqualObjects([[queryCopy.state.extraOptions allValues] lastObject],
[[query.state.extraOptions allValues] lastObject]);
Expand Down

0 comments on commit 98e5faf

Please sign in to comment.