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

@ -12,7 +12,7 @@
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@ -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:
return [leftResult isEqual: rightResult]; if ([rightResult isKindOfClass: [NSString class]])
{
return [leftResult compare: rightResult options: compareOptions] == NSOrderedSame;
}
else
{
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];
@ -1540,7 +1569,7 @@
else else
{ {
l = [NSCompoundPredicate andPredicateWithSubpredicates: l = [NSCompoundPredicate andPredicateWithSubpredicates:
[NSArray arrayWithObjects:l, r, nil]]; [NSArray arrayWithObjects: l, r, nil]];
} }
} }
return l; return l;
@ -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;
[NSException raise: NSInvalidArgumentException if (![a isKindOfClass: [NSArray class]])
format: @"Support for BETWEEN operator is missing"]; {
[NSException raise: NSInvalidArgumentException
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"] ||