From c8ff945f5255a5ffc84dbb631c7207ffc1b780ad Mon Sep 17 00:00:00 2001 From: Dave DeLong Date: Sat, 9 Apr 2011 13:49:05 -0700 Subject: [PATCH] Added methods to execute a query or update with an NSString-style format string --- src/FMDatabase.h | 2 + src/FMDatabase.m | 120 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/FMDatabase.h b/src/FMDatabase.h index f125d61a..2f1e531e 100644 --- a/src/FMDatabase.h +++ b/src/FMDatabase.h @@ -48,10 +48,12 @@ - (BOOL)update:(NSString*)sql error:(NSError**)outErr bind:(id)bindArgs, ...; - (BOOL)executeUpdate:(NSString*)sql, ...; +- (BOOL)executeUpdateWithFormat:(NSString *)format, ...; - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments; - (BOOL)executeUpdate:(NSString*)sql error:(NSError**)outErr withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. - (FMResultSet *)executeQuery:(NSString*)sql, ...; +- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...; - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments; - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead. diff --git a/src/FMDatabase.m b/src/FMDatabase.m index 46d963b5..4430a657 100644 --- a/src/FMDatabase.m +++ b/src/FMDatabase.m @@ -297,6 +297,100 @@ - (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt { } } +- (void)_extractSQL:(NSString *)sql argumentsList:(va_list)args intoString:(NSMutableString *)cleanedSQL arguments:(NSMutableArray *)arguments { + NSUInteger length = [sql length]; + unichar last = '\0'; + for (NSUInteger i = 0; i < length; ++i) { + id arg = nil; + unichar current = [sql characterAtIndex:i]; + unichar add = current; + if (last == '%') { + switch (current) { + case '@': + arg = va_arg(args, id); break; + case 'c': + arg = [NSNumber numberWithChar:va_arg(args, char)]; break; + case 's': + arg = [NSString stringWithUTF8String:va_arg(args, char*)]; break; + case 'd': + case 'D': + case 'i': + arg = [NSNumber numberWithInt:va_arg(args, int)]; break; + case 'u': + case 'U': + arg = [NSNumber numberWithUnsignedInt:va_arg(args, unsigned int)]; break; + case 'h': + i++; + if (i < length && [sql characterAtIndex:i] == 'i') { + arg = [NSNumber numberWithShort:va_arg(args, short)]; + } else if (i < length && [sql characterAtIndex:i] == 'u') { + arg = [NSNumber numberWithUnsignedShort:va_arg(args, unsigned short)]; + } else { + i--; + } + break; + case 'q': + i++; + if (i < length && [sql characterAtIndex:i] == 'i') { + arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; + } else if (i < length && [sql characterAtIndex:i] == 'u') { + arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; + } else { + i--; + } + break; + case 'f': + arg = [NSNumber numberWithDouble:va_arg(args, double)]; break; + case 'g': + arg = [NSNumber numberWithFloat:va_arg(args, float)]; break; + case 'l': + i++; + if (i < length) { + unichar next = [sql characterAtIndex:i]; + if (next == 'l') { + i++; + if (i < length && [sql characterAtIndex:i] == 'd') { + //%lld + arg = [NSNumber numberWithLongLong:va_arg(args, long long)]; + } else if (i < length && [sql characterAtIndex:i] == 'u') { + //%llu + arg = [NSNumber numberWithUnsignedLongLong:va_arg(args, unsigned long long)]; + } else { + i--; + } + } else if (next == 'd') { + //%ld + arg = [NSNumber numberWithLong:va_arg(args, long)]; + } else if (next == 'u') { + //%lu + arg = [NSNumber numberWithUnsignedLong:va_arg(args, unsigned long)]; + } else { + i--; + } + } else { + i--; + } + break; + default: + // something else that we can't interpret. just pass it on through like normal + break; + } + } else if (current == '%') { + // percent sign; skip this character + add = '\0'; + } + + if (arg != nil) { + [cleanedSQL appendString:@"?"]; + [arguments addObject:arg]; + } else if (add != '\0') { + [cleanedSQL appendFormat:@"%C", add]; + } + last = current; + } + +} + - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args { if (inUse) { @@ -428,6 +522,19 @@ - (FMResultSet *)executeQuery:(NSString*)sql, ... { return result; } +- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ... { + va_list args; + va_start(args, format); + + NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; + NSMutableArray *arguments = [NSMutableArray array]; + [self _extractSQL:format argumentsList:args intoString:sql arguments:arguments]; + + va_end(args); + + return [self executeQuery:sql withArgumentsInArray:arguments]; +} + - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments { return [self executeQuery:sql withArgumentsInArray:arguments orVAList:nil]; } @@ -623,6 +730,19 @@ - (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments { return [self executeUpdate:sql error:nil withArgumentsInArray:arguments orVAList:nil]; } +- (BOOL)executeUpdateWithFormat:(NSString*)format, ... { + va_list args; + va_start(args, format); + + NSMutableString *sql = [NSMutableString stringWithCapacity:[format length]]; + NSMutableArray *arguments = [NSMutableArray array]; + [self _extractSQL:format argumentsList:args intoString:sql arguments:arguments]; + + va_end(args); + + return [self executeUpdate:sql withArgumentsInArray:arguments]; +} + - (BOOL)update:(NSString*)sql error:(NSError**)outErr bind:(id)bindArgs, ... { va_list args; va_start(args, bindArgs);