我终于完成了自己的类,希望能对你们有所帮助。
.H文件:
@interface PredicateToSQL : NSObject
+ (PredicateToSQL *) sharedObject;
- (NSString *) SQLFilterForPredicate:(NSPredicate *)predicate;
@end
.M File
#import "PredicateToSQL.h"
@implementation PredicateToSQL
static NSString *SQLNullValueString = @"NULL";
static PredicateToSQL *sharedObject;
+ (PredicateToSQL *) sharedObject
{
return sharedObject;
}
+ (void) initialize
{
sharedObject = [PredicateToSQL new];
}
- (NSString *)SQLExpressionForKeyPath:(NSString *)keyPath
{
NSString *retStr = nil;
NSDictionary *convertibleSetOperations = @{@"@avg" : @"avg",@"@max" : @"max",@"@min" : @"min",@"@sum" : @"sum",@"@distinctUnionOfObjects" : @"distinct" };
for (NSString *setOpt in [convertibleSetOperations allKeys])
{ if ([keyPath hasSuffix:setOpt])
{ NSString *clean = [[keyPath stringByReplacingOccurrencesOfString:setOpt withString:@""] stringByReplacingOccurrencesOfString:@".." withString:@"."];
retStr = [NSString stringWithFormat:@"%@(%@)",convertibleSetOperations[setOpt], clean];
};
};
if (retStr != nil) return(retStr);
return(keyPath);
}
- (NSString *) SQLSelectClauseForSubqueryExpression:(NSExpression *)expression
{
PSLog(@"SQLSelectClauseForSubqueryExpression not implemented");
return(nil);
}
- (NSString *) SQLLiteralListForArray:(NSArray *)array
{
NSMutableArray *retArray = [NSMutableArray array];
for (NSExpression *obj in array) { [retArray addObject:[self SQLExpressionForNSExpression:obj]]; };
return([NSString stringWithFormat:@"(%@)",[retArray componentsJoinedByString:@","]]);
}
- (NSString *) SQLFunctionLiteralForFunctionExpression:(NSExpression *)exp
{
NSDictionary *convertibleNullaryFunctions = @{ @"now" : @"date('now')",@"random" : @"random()" };
NSDictionary *convertibleUnaryFunctions = @{ @"uppercase:" : @"upper",@"lowercase:" : @"lower",@"abs:" : @"abs" };
NSDictionary *convertibleBinaryFunctions = @{ @"add:to:" : @"+" ,
@"from:subtract:" : @"-" ,
@"multiply:by:" : @"*" ,
@"divide:by:" : @"/" ,
@"modulus:by:" : @"%" ,
@"leftshift:by" : @"<<",
@"rightshift:by:" : @">>"
};
if ([[convertibleNullaryFunctions allKeys] containsObject:[exp function]])
{ return(convertibleNullaryFunctions[[exp function]]);
}
else { if ([[convertibleUnaryFunctions allKeys] containsObject:[exp function]])
{ return([NSString stringWithFormat:@"%@(%@)",convertibleUnaryFunctions[[exp function]],[self SQLExpressionForNSExpression:[exp arguments][0]]]);
}
else { if ([[convertibleBinaryFunctions allKeys] containsObject:[exp function]])
{ return([NSString stringWithFormat:@"(%@ %@ %@)",[self SQLExpressionForNSExpression:[exp arguments][0]],convertibleBinaryFunctions[[exp function]],[self SQLExpressionForNSExpression:[exp arguments][1]]]);
}
else { PSLog(@"SQLFunctionLiteralForFunctionExpression could not be converted because it uses an unconvertible function");
};
};
};
return(nil);
}
- (NSString *) SQLNamedReplacementVariableForVariable:(NSString *)var
{
return(var);
}
- (NSString *)DatabaseKeyfor:(NSString *)obj
{
NSArray *keysForObj = [DatabaseDictionary allKeysForObject:obj];
if ([keysForObj count] > 0) return([keysForObj objectAtIndex:0]);
return(obj);
}
- (NSString *)SQLExpressionForLeftKeyPath:(NSString *)keyPath
{
NSString *retStr = nil;
NSDictionary *convertibleSetOperations = @{ @"@avg" : @"avg",@"@max" : @"max",@"@min" : @"min",@"@sum" : @"sum",@"@distinctUnionOfObjects" : @"distinct" };
for (NSString *setOpt in [convertibleSetOperations allKeys])
{ if ([keyPath hasSuffix:setOpt])
{ NSString *clean = [[keyPath stringByReplacingOccurrencesOfString:setOpt withString:@""] stringByReplacingOccurrencesOfString:@".." withString:@"."];
retStr = [NSString stringWithFormat:@"%@(%@)",convertibleSetOperations[setOpt],clean];
};
};
if (retStr != nil) return([self DatabaseKeyfor:retStr]);
return([self DatabaseKeyfor:keyPath]);
}
- (NSString *) SQLConstantForLeftValue:(id) val
{
if (val == nil) return(SQLNullValueString);
if ([val isEqual:[NSNull null]]) return(SQLNullValueString);
if ([val isKindOfClass:[NSString class]])
{
return([self DatabaseKeyfor:val]);
}
else { if ([val respondsToSelector:@selector(intValue)])
{ return([self DatabaseKeyfor:[val stringValue]]);
}
else { return([self SQLConstantForLeftValue:[val description]]);
};
};
return(nil);
}
-(NSString *)SQLExpressionForLeftNSExpression:(NSExpression *)expression
{
NSString *retStr = nil;
switch ([expression expressionType])
{ case NSConstantValueExpressionType: { retStr = [self SQLConstantForLeftValue:[expression constantValue]];
break; }
case NSVariableExpressionType: { retStr = [self SQLNamedReplacementVariableForVariable:[expression variable]];
break; }
case NSKeyPathExpressionType: { retStr = [self SQLExpressionForLeftKeyPath:[expression keyPath]];
break; }
case NSFunctionExpressionType: { retStr = [self SQLFunctionLiteralForFunctionExpression:expression];
break; }
case NSSubqueryExpressionType: { retStr = [self SQLSelectClauseForSubqueryExpression:expression];
break; }
case NSAggregateExpressionType: { retStr = [self SQLLiteralListForArray:[expression collection]];
break; }
case NSUnionSetExpressionType: { break; }
case NSIntersectSetExpressionType: { break; }
case NSMinusSetExpressionType: { break; }
case NSEvaluatedObjectExpressionType: { break; }
case NSBlockExpressionType: { break; }
};
return retStr;
}
-(NSString *)SQLConstantForValue:(id) val
{
if (val == nil) return(SQLNullValueString);
if ([val isEqual:[NSNull null]]) return(SQLNullValueString);
if ([val isKindOfClass:[NSString class]])
{
return(val);
}
else { if ([val respondsToSelector:@selector(intValue)])
{ return([val stringValue]);
}
else { return([self SQLConstantForValue:[val description]]);
};
};
return(nil);
}
-(NSString *)SQLExpressionForNSExpression:(NSExpression *)expression
{
NSString *retStr = nil;
switch ([expression expressionType])
{ case NSConstantValueExpressionType: { retStr = [self SQLConstantForValue:[expression constantValue]];
break; }
case NSVariableExpressionType: { retStr = [self SQLNamedReplacementVariableForVariable:[expression variable]];
break; }
case NSKeyPathExpressionType: { retStr = [self SQLExpressionForKeyPath:[expression keyPath]];
break; }
case NSFunctionExpressionType: { retStr = [self SQLFunctionLiteralForFunctionExpression:expression];
break; }
case NSSubqueryExpressionType: { retStr = [self SQLSelectClauseForSubqueryExpression:expression];
break; }
case NSAggregateExpressionType: { retStr = [self SQLLiteralListForArray:[expression collection]];
break; }
case NSUnionSetExpressionType: { break; }
case NSIntersectSetExpressionType: { break; }
case NSMinusSetExpressionType: { break; }
case NSEvaluatedObjectExpressionType: { break; }
case NSBlockExpressionType: { break; }
};
return retStr;
}
- (NSString *) SQLWhereClauseForComparisonPredicate:(NSComparisonPredicate *)predicate
{
NSString *leftSQLExpression = [self SQLExpressionForLeftNSExpression:[predicate leftExpression]];
NSString *rightSQLExpression = [self SQLExpressionForNSExpression:[predicate rightExpression]];
switch ([predicate predicateOperatorType])
{ case NSLessThanPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ < '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSLessThanOrEqualToPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ <= '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSGreaterThanPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ > '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSGreaterThanOrEqualToPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ >= '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSEqualToPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ = '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSNotEqualToPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ <> '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSMatchesPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ MATCH '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSInPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ IN '%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSBetweenPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ BETWEEN '%@' AND '%@')",[self SQLExpressionForLeftNSExpression:[predicate leftExpression]],
[self SQLExpressionForNSExpression:[[predicate rightExpression] collection][0]],
[self SQLExpressionForNSExpression:[[predicate rightExpression] collection][1]]]);
break; }
case NSLikePredicateOperatorType:
case NSContainsPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ LIKE '%%%@%%')",leftSQLExpression,rightSQLExpression]);
break; }
case NSBeginsWithPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ LIKE '%@%%')",leftSQLExpression,rightSQLExpression]);
break; }
case NSEndsWithPredicateOperatorType: { return([NSString stringWithFormat:@"(%@ LIKE '%%%@')",leftSQLExpression,rightSQLExpression]);
break; }
case NSCustomSelectorPredicateOperatorType: { PSLog(@"SQLWhereClauseForComparisonPredicate custom selectors are not supported");
break; }
};
return(nil);
}
- (NSString *) SQLWhereClauseForCompoundPredicate:(NSCompoundPredicate *)predicate
{
NSMutableArray *subs = [NSMutableArray array];
for (NSPredicate *sub in [predicate subpredicates]) { [subs addObject:[self SQLFilterForPredicate:sub]]; };
NSString *conjunction;
switch ([(NSCompoundPredicate *)predicate compoundPredicateType])
{ case NSAndPredicateType: { conjunction = @" AND "; break; }
case NSOrPredicateType: { conjunction = @" OR "; break; }
case NSNotPredicateType: { conjunction = @" NOT "; break; }
default: { conjunction = @" "; break; }
};
return([NSString stringWithFormat:@"(%@)", [subs componentsJoinedByString:conjunction]]);
}
- (NSString *)SQLFilterForPredicate:(NSPredicate *)predicate
{
if ([predicate respondsToSelector:@selector(compoundPredicateType)])
{ return([self SQLWhereClauseForCompoundPredicate:(NSCompoundPredicate *)predicate]);
}
else { if ([predicate respondsToSelector:@selector(predicateOperatorType)])
{ return([self SQLWhereClauseForComparisonPredicate:(NSComparisonPredicate *)predicate]);
}
else { PSLog(@"SQLFilterForPredicate predicate is not of a convertible class");
}
};
return(nil);
}
@end
您可以在某些全局变量中创建自己的数据库信息,如下所示。
gDatabaseTitles = [NSArray arrayWithObjects:@"Name",@"Phone Number",@"Location",@"Date Of Birth",@"Miscellaneous",nil];
gDatabaseKeys = [NSArray arrayWithObjects:@"name",@"phone_number",@"location",@"date_of_birth",@"misc",nil];
gDatabaseTypes = [NSArray arrayWithObjects:@"name TEXT",@"phone_number TEXT",@"location TEXT",@"date_of_birth DATE",@"misc TEXT",nil];
gDatabaseDictionary = [NSDictionary dictionaryWithObjects:gPatientDatabaseTitles forKeys:gPatientDatabaseKeys];
我不得不编辑很多代码,以去掉与我的项目相关的内容,所以如果我漏掉了什么,这段代码可能无法编译,但这是有效的概念。如果您有任何问题,请让我知道,我会进行修复。在任何您看到gVariable的地方,那是我所指的全局变量,在我的项目中帮助了我,也可能对您有帮助。
NSString *SQLWhereClauseForPredictate(NSPredicate *predicate)
与您建议的原型一样拼写错误 "Predictate" :-) - Martin R