[ios, macos] Aggregate equality predicates

Added support for “ANY … =” and “ALL … !=” as synonyms for “IN” and “NOT IN”, respectively.
This commit is contained in:
Minh Nguyễn
2020-02-27 19:10:18 -08:00
committed by Minh Nguyễn
parent bc6f434a88
commit fb559ea8d4
2 changed files with 107 additions and 0 deletions

View File

@@ -79,6 +79,52 @@
@implementation NSComparisonPredicate (MGLExpressionAdditions)
- (id)mgl_jsonExpressionObject {
switch (self.comparisonPredicateModifier) {
case NSDirectPredicateModifier:
break;
case NSAllPredicateModifier:
// “ALL x != y” is logically equivalent to “NOT y IN x”.
if (self.predicateOperatorType == NSNotEqualToPredicateOperatorType) {
// https://github.com/mapbox/mapbox-gl-js/issues/9339
if (self.options) {
[NSException raise:NSInvalidArgumentException format:@"NSComparisonPredicateOptions not supported for “ALL … !=” comparisons."];
}
NSPredicate *directPredicate = [NSComparisonPredicate predicateWithLeftExpression:self.rightExpression
rightExpression:self.leftExpression
modifier:NSDirectPredicateModifier
type:NSInPredicateOperatorType
options:self.options];
NSPredicate *invertedPredicate = [NSCompoundPredicate notPredicateWithSubpredicate:directPredicate];
return invertedPredicate.mgl_jsonExpressionObject;
} else {
[NSException raise:NSInvalidArgumentException format:@"“ALL” is only supported for the “!=” operator."];
}
case NSAnyPredicateModifier:
// “ANY x = y” is logically equivalent to “y IN x”.
if (self.predicateOperatorType == NSEqualToPredicateOperatorType) {
// https://github.com/mapbox/mapbox-gl-js/issues/9339
if (self.options) {
[NSException raise:NSInvalidArgumentException format:@"NSComparisonPredicateOptions not supported for “ANY … =” comparisons."];
}
NSPredicate *directPredicate = [NSComparisonPredicate predicateWithLeftExpression:self.rightExpression
rightExpression:self.leftExpression
modifier:NSDirectPredicateModifier
type:NSInPredicateOperatorType
options:self.options];
return directPredicate.mgl_jsonExpressionObject;
} else {
[NSException raise:NSInvalidArgumentException format:@"“ANY” or “SOME” is only supported for the “=” operator."];
}
default:
[NSException raise:NSInvalidArgumentException
format:@"NSComparisonPredicateModifier:%lu is not supported.", (unsigned long)self.comparisonPredicateModifier];
}
NSString *op;
switch (self.predicateOperatorType) {
case NSLessThanPredicateOperatorType:

View File

@@ -315,6 +315,53 @@
XCTAssertEqualObjects([NSPredicate predicateWithMGLJSONObject:expected], predicateAfter);
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:predicate.mgl_filter], [NSPredicate predicateWithValue:NO]);
}
{
NSArray *expected = @[@"in", @[@"id"], @[@"literal", @[@6, @5, @4, @3]]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY {6, 5, 4, 3} = $featureIdentifier"];
XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"$featureIdentifier IN {6, 5, 4, 3}"];
XCTAssertEqualObjects([NSPredicate predicateWithMGLJSONObject:expected], predicateAfter);
[self testSymmetryWithPredicate:[NSPredicate predicateWithMGLJSONObject:expected]
mustRoundTrip:YES];
}
{
NSArray *expected = @[@"!", @[@"in", @[@"id"], @[@"literal", @[@6, @5, @4, @3]]]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE {6, 5, 4, 3} = $featureIdentifier"];
XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"NOT $featureIdentifier IN {6, 5, 4, 3}"];
XCTAssertEqualObjects([NSPredicate predicateWithMGLJSONObject:expected], predicateAfter);
[self testSymmetryWithPredicate:[NSPredicate predicateWithMGLJSONObject:expected]
mustRoundTrip:YES];
}
{
NSArray *expected = @[@"!", @[@"in", @[@"id"], @[@"literal", @[@6, @5, @4, @3]]]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL {6, 5, 4, 3} != $featureIdentifier"];
XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"NOT $featureIdentifier IN {6, 5, 4, 3}"];
XCTAssertEqualObjects([NSPredicate predicateWithMGLJSONObject:expected], predicateAfter);
[self testSymmetryWithPredicate:[NSPredicate predicateWithMGLJSONObject:expected]
mustRoundTrip:YES];
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY {6, 5, 4, 3} != $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY {6, 5, 4, 3} > $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE {6, 5, 4, 3} != $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL {6, 5, 4, 3} = $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL {6, 5, 4, 3} < $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
}
- (void)testComparisonPredicatesWithOptions {
@@ -388,6 +435,20 @@
@"locale": @"tlh"}]];
XCTAssertEqualObjects([predicate.mgl_jsonExpressionObject lastObject], jsonExpression);
}
// https://github.com/mapbox/mapbox-gl-js/issues/9339
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY {6, 5, 4, 3} =[c] $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE {6, 5, 4, 3} =[d] $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL {6, 5, 4, 3} !=[cd] $featureIdentifier"];
XCTAssertThrowsSpecificNamed(predicate.mgl_jsonExpressionObject, NSException, NSInvalidArgumentException);
}
}
- (void)testCompoundPredicates {