Improved predicate parsing.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@25235 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2007-06-11 10:56:36 +00:00
parent fb6739feb4
commit eab08f939e
2 changed files with 80 additions and 17 deletions

View file

@ -1,3 +1,9 @@
2007-06-11 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSPredicate.m: Improved predicate parsing. Handle more
alternate key strings, implemented BETWEEN, use compare:options:
for string equality test and handle in for collections.
2007-06-09 Fred Kiefer <FredKiefer@gmx.de> 2007-06-09 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSPredicate.m: Improved predicate parsing. * Source/NSPredicate.m: Improved predicate parsing.

View file

@ -75,6 +75,7 @@
- (NSExpression *) parseMultiplicationExpression; - (NSExpression *) parseMultiplicationExpression;
- (NSExpression *) parseAdditionExpression; - (NSExpression *) parseAdditionExpression;
- (NSExpression *) parseBinaryExpression; - (NSExpression *) parseBinaryExpression;
- (NSExpression *) parseSimpleExpression;
@end @end
@ -715,7 +716,14 @@
case NSGreaterThanOrEqualToPredicateOperatorType: case NSGreaterThanOrEqualToPredicateOperatorType:
return ([leftResult compare: rightResult] != NSOrderedAscending); return ([leftResult compare: rightResult] != NSOrderedAscending);
case NSEqualToPredicateOperatorType: case NSEqualToPredicateOperatorType:
if ([rightResult isKindOfClass: [NSString class]])
{
return [leftResult compare: rightResult options: compareOptions] == NSOrderedSame;
}
else
{
return [leftResult isEqual: rightResult]; return [leftResult isEqual: rightResult];
}
case NSNotEqualToPredicateOperatorType: case NSNotEqualToPredicateOperatorType:
return ![leftResult isEqual: rightResult]; return ![leftResult isEqual: rightResult];
case NSMatchesPredicateOperatorType: case NSMatchesPredicateOperatorType:
@ -735,7 +743,27 @@
return ([leftResult compare: rightResult options: compareOptions range: range] == NSOrderedSame); return ([leftResult compare: rightResult options: compareOptions range: range] == NSOrderedSame);
} }
case NSInPredicateOperatorType: case NSInPredicateOperatorType:
// FIXME: Handle special case where rightResult is a collection and leftResult an element of it. // Handle special case where rightResult is a collection and leftResult an element of it.
if (![rightResult isKindOfClass: [NSString class]])
{
NSEnumerator *e;
id value;
if (![rightResult respondsToSelector: @selector(objectEnumerator)])
{
[NSException raise: NSInvalidArgumentException
format: @"The right hand side for an IN operator must be a collection"];
}
e = [rightResult objectEnumerator];
while ((value = [e nextObject]))
{
if ([value isEqual: leftResult])
return YES;
}
return NO;
}
return ([leftResult rangeOfString: rightResult options: compareOptions].location != NSNotFound); return ([leftResult rangeOfString: rightResult options: compareOptions].location != NSNotFound);
case NSCustomSelectorPredicateOperatorType: case NSCustomSelectorPredicateOperatorType:
{ {
@ -1506,7 +1534,8 @@
{ {
NSPredicate *l = [self parseOr]; NSPredicate *l = [self parseOr];
while ([self scanPredicateKeyword: @"AND"]) while ([self scanPredicateKeyword: @"AND"] ||
[self scanPredicateKeyword: @"&&"])
{ {
NSPredicate *r = [self parseOr]; NSPredicate *r = [self parseOr];
@ -1583,7 +1612,8 @@
{ {
NSPredicate *l = [self parseNot]; NSPredicate *l = [self parseNot];
while ([self scanPredicateKeyword: @"OR"]) while ([self scanPredicateKeyword: @"OR"] ||
[self scanPredicateKeyword: @"||"])
{ {
NSPredicate *r = [self parseNot]; NSPredicate *r = [self parseNot];
@ -1656,7 +1686,8 @@
{ {
type = NSLessThanPredicateOperatorType; type = NSLessThanPredicateOperatorType;
} }
else if ([self scanString: @"<=" intoString: NULL]) else if ([self scanString: @"<=" intoString: NULL] ||
[self scanString: @"=<" intoString: NULL])
{ {
type = NSLessThanOrEqualToPredicateOperatorType; type = NSLessThanOrEqualToPredicateOperatorType;
} }
@ -1664,7 +1695,8 @@
{ {
type = NSGreaterThanPredicateOperatorType; type = NSGreaterThanPredicateOperatorType;
} }
else if ([self scanString: @">=" intoString: NULL]) else if ([self scanString: @">=" intoString: NULL] ||
[self scanString: @"=>" intoString: NULL])
{ {
type = NSGreaterThanOrEqualToPredicateOperatorType; type = NSGreaterThanOrEqualToPredicateOperatorType;
} }
@ -1673,7 +1705,8 @@
{ {
type = NSEqualToPredicateOperatorType; type = NSEqualToPredicateOperatorType;
} }
else if ([self scanString: @"!=" intoString: NULL]) else if ([self scanString: @"!=" intoString: NULL] ||
[self scanString: @"<>" intoString: NULL])
{ {
type = NSNotEqualToPredicateOperatorType; type = NSNotEqualToPredicateOperatorType;
} }
@ -1693,17 +1726,43 @@
{ {
type = NSEndsWithPredicateOperatorType; type = NSEndsWithPredicateOperatorType;
} }
else if ([self scanPredicateKeyword: @"IN"]) else if ([self scanPredicateKeyword: @"IN"] ||
[self scanPredicateKeyword: @"CONTAINS"])
{ {
type = NSInPredicateOperatorType; type = NSInPredicateOperatorType;
} }
else if ([self scanPredicateKeyword: @"BETWEEN"]) else if ([self scanPredicateKeyword: @"BETWEEN"])
{ {
// FIXME: Requires special handling to transfer into AND of // Requires special handling to transfer into AND of
// two normal comparison predicates // two normal comparison predicates
NSExpression *exp = [self parseSimpleExpression];
NSArray *a = (NSArray *)[exp constantValue];
NSNumber *lower, *upper;
NSExpression *lexp, *uexp;
NSPredicate *lp, *up;
if (![a isKindOfClass: [NSArray class]])
{
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Support for BETWEEN operator is missing"]; format: @"BETWEEN operator requires array argument"];
}
lower = [a objectAtIndex: 0];
upper = [a objectAtIndex: 1];
lexp = [NSExpression expressionForConstantValue: lower];
uexp = [NSExpression expressionForConstantValue: upper];
lp = [NSComparisonPredicate predicateWithLeftExpression: left
rightExpression: lexp
modifier: modifier
type: NSGreaterThanPredicateOperatorType
options: opts];
up = [NSComparisonPredicate predicateWithLeftExpression: left
rightExpression: uexp
modifier: modifier
type: NSLessThanPredicateOperatorType
options: opts];
return [NSCompoundPredicate andPredicateWithSubpredicates:
[NSArray arrayWithObjects: lp, up, nil]];
} }
else else
{ {
@ -1779,8 +1838,7 @@
if ([self scanString: @"}" intoString: NULL]) if ([self scanString: @"}" intoString: NULL])
{ {
// empty // empty
// FIXME return [NSExpression expressionForConstantValue: a];
return nil;
} }
// first element // first element
[a addObject: [self parseExpression]]; [a addObject: [self parseExpression]];
@ -1795,8 +1853,7 @@
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Missing } in aggregate"]; format: @"Missing } in aggregate"];
} }
// FIXME return [NSExpression expressionForConstantValue: a];
return nil;
} }
if ([self scanPredicateKeyword: @"NULL"] || if ([self scanPredicateKeyword: @"NULL"] ||