终于自己开课了,希望对大家有帮助。
.H 文件
@interface PredicateToSQL : NSObject
+ (PredicateToSQL *) sharedObject;
- (NSString *) SQLFilterForPredicate:(NSPredicate *)predicate;
@end
.M 文件
#import "PredicateToSQL.h"
@implementation PredicateToSQL
static NSString *SQLNullValueString = @"NULL";
/* Implementation */
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
{
//PSLog(@"SQLNamedReplacementVariableForVariable not implemented");
return(var);
}
/*
NSArray *temp = [gPatientDatabaseDictionary allKeysForObject:var];
NSString *key = [temp objectAtIndex:0];
return(key);
*/
- (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]])
{ //PSLog(@"SQLConstantForLeftValue val %@",val);
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]];
//NSLog(@"LEFT NSConstantValueExpressionType %@",retStr); // contains 'Patient Name' etc..
break; }
case NSVariableExpressionType: { retStr = [self SQLNamedReplacementVariableForVariable:[expression variable]];
//NSLog(@"LEFT NSVariableExpressionType %@",retStr);
break; }
case NSKeyPathExpressionType: { retStr = [self SQLExpressionForLeftKeyPath:[expression keyPath]];
//NSLog(@"LEFT NSKeyPathExpressionType %@",retStr); // first "Patient Name'
break; }
case NSFunctionExpressionType: { retStr = [self SQLFunctionLiteralForFunctionExpression:expression];
//NSLog(@"LEFT NSFunctionExpressionType %@",retStr);
break; }
case NSSubqueryExpressionType: { retStr = [self SQLSelectClauseForSubqueryExpression:expression];
//NSLog(@"LEFT NSSubqueryExpressionType %@",retStr);
break; }
case NSAggregateExpressionType: { retStr = [self SQLLiteralListForArray:[expression collection]];
//NSLog(@"LEFT NSAggregateExpressionType %@",retStr);
break; }
case NSUnionSetExpressionType: { break; }
case NSIntersectSetExpressionType: { break; }
case NSMinusSetExpressionType: { break; }
case NSEvaluatedObjectExpressionType: { break; } // these can't be converted
case NSBlockExpressionType: { break; }
//case NSAnyKeyExpressionType: { break; }
};
return retStr;
}
-(NSString *)SQLConstantForValue:(id) val
{
if (val == nil) return(SQLNullValueString);
if ([val isEqual:[NSNull null]]) return(SQLNullValueString);
if ([val isKindOfClass:[NSString class]])
{ //NSLog(@"SQLConstantForValue val %@",val);
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]];
//NSLog(@"NSConstantValueExpressionType %@",retStr); // contains 'Patient Name' etc..
break; }
case NSVariableExpressionType: { retStr = [self SQLNamedReplacementVariableForVariable:[expression variable]];
//NSLog(@"NSVariableExpressionType %@",retStr);
break; }
case NSKeyPathExpressionType: { retStr = [self SQLExpressionForKeyPath:[expression keyPath]];
//NSLog(@"NSKeyPathExpressionType %@",retStr);
break; }
case NSFunctionExpressionType: { retStr = [self SQLFunctionLiteralForFunctionExpression:expression];
//NSLog(@"NSFunctionExpressionType %@",retStr);
break; }
case NSSubqueryExpressionType: { retStr = [self SQLSelectClauseForSubqueryExpression:expression];
//NSLog(@"NSSubqueryExpressionType %@",retStr);
break; }
case NSAggregateExpressionType: { retStr = [self SQLLiteralListForArray:[expression collection]];
//PSLog(@"NSAggregateExpressionType %@",retStr);
break; }
case NSUnionSetExpressionType: { break; }
case NSIntersectSetExpressionType: { break; }
case NSMinusSetExpressionType: { break; }
case NSEvaluatedObjectExpressionType: { break; } // these can't be converted
case NSBlockExpressionType: { break; }
//case NSAnyKeyExpressionType: { break; }
};
return retStr;
}
/*
- (NSString *) SQLInfixOperatorForOperatorType:(NSPredicateOperatorType) type
{
switch (type)
{ case NSLessThanPredicateOperatorType: { return(@"<");
break; }
case NSLessThanOrEqualToPredicateOperatorType: { return(@"<=");
break; }
case NSGreaterThanPredicateOperatorType: { return(@">");
break; }
case NSGreaterThanOrEqualToPredicateOperatorType: { return(@">=");
break; }
case NSEqualToPredicateOperatorType: { return(@"=");
break; }
case NSNotEqualToPredicateOperatorType: { return(@"<>");
break; }
case NSMatchesPredicateOperatorType: { return(@"MATCH");
break; }
case NSInPredicateOperatorType: { return(@"IN");
break; }
case NSBetweenPredicateOperatorType: { return(@"BETWEEN");
break; }
case NSLikePredicateOperatorType: { return(@"LIKE");
break; }
case NSContainsPredicateOperatorType: { return(@"CONTAINS");
break; }
case NSBeginsWithPredicateOperatorType:
case NSEndsWithPredicateOperatorType: { //NSAssert(0,@"predicate not converted because 'beginswith' and 'endswith' are not consistently supported by SQL");
break; }
case NSCustomSelectorPredicateOperatorType: { //NSAssert(0,@"predicate cannot be converted to a where clause because it calls a custom selector");
break; }
};
return(nil);
}
*/
- (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; }
};
/*
//NSAssert(0,@"predicate not converted because 'beginswith' and 'endswith' are not consistently supported by SQL");
//NSAssert(0,@"predicate cannot be converted to a where clause because it calls a custom selector");
NSString *comparator = [self SQLInfixOperatorForOperatorType:[predicate predicateOperatorType]];
if (comparator != nil)
{ if ([comparator isEqual:@"BETWEEN"])
{ return([NSString stringWithFormat:@"(%@ %@ '%@' AND '%@')",[self SQLExpressionForLeftNSExpression:[predicate leftExpression]],comparator,
[self SQLExpressionForNSExpression:[[predicate rightExpression] collection][0]],
[self SQLExpressionForNSExpression:[[predicate rightExpression] collection][1]]]);
}
else { if ([comparator isEqual:@"CONTAINS"])
{ return([NSString stringWithFormat:@"(%@ LIKE '%%%@%%')",[self SQLExpressionForLeftNSExpression:[predicate leftExpression]],
[self SQLExpressionForNSExpression:[predicate rightExpression]]]);
}
else { return([NSString stringWithFormat:@"(%@ %@ '%@')",[self SQLExpressionForLeftNSExpression:[predicate leftExpression]],comparator,
[self SQLExpressionForNSExpression:[predicate rightExpression]]]);
};
};
} else { PSLog(@"SQLWhereClauseForComparisonPredicate predicate could not be converted to comparator"); };
*/
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; }
};
//NSLog(@"SQLWhereClauseForCompoundPredicate conjunction %@",conjunction);
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 都是我指的一个全局变量,它对我的项目有帮助,并且可能会对你有所帮助。