Skip to content

feat: Add support to exclude PFObject fields in query results with PFQuery.excludeKeys #1731

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

Merged
merged 4 commits into from
Jul 11, 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
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