Authored by Foobaz

Updated base SDK to OS 3.2 for compabitility with newer Xcode. Made static analy…

…zer happy. Updated FMDB to latest version.

... ... @@ -22,7 +22,10 @@
- (id)initWithPath:(NSString*)inPath;
- (BOOL) open;
- (void) close;
#if SQLITE_VERSION_NUMBER >= 3005000
- (BOOL) openWithFlags:(int)flags;
#endif
- (BOOL) close;
- (BOOL) goodConnection;
- (void) clearCachedStatements;
... ... @@ -41,11 +44,13 @@
- (sqlite3*) sqliteHandle;
- (BOOL) executeUpdate:(NSString *)sql arguments:(va_list)args;
- (BOOL) executeUpdate:(NSString*)sql, ...;
- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
- (id) executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead.
- (id) executeQuery:(NSString *)sql arguments:(va_list)args;
- (id) executeQuery:(NSString*)sql, ...;
- (id) executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args; // you shouldn't ever need to call this. use the previous two instead.
- (BOOL) rollback;
- (BOOL) commit;
... ...
... ... @@ -4,7 +4,7 @@
@implementation FMDatabase
+ (id)databaseWithPath:(NSString*)aPath {
return [[[FMDatabase alloc] initWithPath:aPath] autorelease];
return [[[self alloc] initWithPath:aPath] autorelease];
}
- (id)initWithPath:(NSString*)aPath {
... ... @@ -43,21 +43,33 @@
}
- (BOOL) open {
int err = sqlite3_open( [databasePath fileSystemRepresentation], &db );
int err = sqlite3_open([databasePath fileSystemRepresentation], &db );
if(err != SQLITE_OK) {
RMLog(@"error opening!: %d", err);
NSLog(@"error opening!: %d", err);
return NO;
}
return YES;
}
- (void) close {
#if SQLITE_VERSION_NUMBER >= 3005000
- (BOOL) openWithFlags:(int)flags {
int err = sqlite3_open_v2([databasePath fileSystemRepresentation], &db, flags, NULL /* Name of VFS module to use */);
if(err != SQLITE_OK) {
NSLog(@"error opening!: %d", err);
return NO;
}
return YES;
}
#endif
- (BOOL) close {
[self clearCachedStatements];
if (!db) {
return;
return YES;
}
int rc;
... ... @@ -70,18 +82,19 @@
retry = YES;
usleep(20);
if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) {
RMLog(@"%s:%d", __FUNCTION__, __LINE__);
RMLog(@"Database busy, unable to close");
return;
NSLog(@"%s:%d", __FUNCTION__, __LINE__);
NSLog(@"Database busy, unable to close");
return NO;
}
}
else if (SQLITE_OK != rc) {
RMLog(@"error closing!: %d", rc);
NSLog(@"error closing!: %d", rc);
}
}
while (retry);
db = nil;
return YES;
}
- (void) clearCachedStatements {
... ... @@ -101,7 +114,7 @@
}
- (void) setCachedStatement:(FMStatement*)statement forQuery:(NSString*)query {
//RMLog(@"setting query: %@", query);
//NSLog(@"setting query: %@", query);
query = [query copy]; // in case we got handed in a mutable string...
[statement setQuery:query];
[cachedStatements setObject:statement forKey:query];
... ... @@ -118,8 +131,8 @@
int rc = sqlite3_rekey(db, [key UTF8String], strlen([key UTF8String]));
if (rc != SQLITE_OK) {
RMLog(@"error on rekey: %d", rc);
RMLog(@"%@", [self lastErrorMessage]);
NSLog(@"error on rekey: %d", rc);
NSLog(@"%@", [self lastErrorMessage]);
}
return (rc == SQLITE_OK);
... ... @@ -159,7 +172,7 @@
}
- (void) compainAboutInUse {
RMLog(@"The FMDatabase %@ is currently in use.", self);
NSLog(@"The FMDatabase %@ is currently in use.", self);
if (crashOnErrors) {
NSAssert1(false, @"The FMDatabase %@ is currently in use.", self);
... ... @@ -171,7 +184,9 @@
}
- (BOOL) hadError {
return ([self lastErrorCode] != SQLITE_OK);
int lastErrCode = [self lastErrorCode];
return (lastErrCode > SQLITE_OK && lastErrCode < SQLITE_ROW);
}
- (int) lastErrorCode {
... ... @@ -201,7 +216,7 @@
// FIXME - someday check the return codes on these binds.
else if ([obj isKindOfClass:[NSData class]]) {
sqlite3_bind_blob(pStmt, idx, [obj bytes], [obj length], SQLITE_STATIC);
sqlite3_bind_blob(pStmt, idx, [obj bytes], (int)[obj length], SQLITE_STATIC);
}
else if ([obj isKindOfClass:[NSDate class]]) {
sqlite3_bind_double(pStmt, idx, [obj timeIntervalSince1970]);
... ... @@ -217,6 +232,9 @@
else if (strcmp([obj objCType], @encode(long)) == 0) {
sqlite3_bind_int64(pStmt, idx, [obj longValue]);
}
else if (strcmp([obj objCType], @encode(long long)) == 0) {
sqlite3_bind_int64(pStmt, idx, [obj longLongValue]);
}
else if (strcmp([obj objCType], @encode(float)) == 0) {
sqlite3_bind_double(pStmt, idx, [obj floatValue]);
}
... ... @@ -232,7 +250,7 @@
}
}
- (id) executeQuery:(NSString *)sql arguments:(va_list)args {
- (id) executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args {
if (inUse) {
[self compainAboutInUse];
... ... @@ -248,7 +266,7 @@
FMStatement *statement = 0x00;
if (traceExecution && sql) {
RMLog(@"%@ executeQuery: %@", self, sql);
NSLog(@"%@ executeQuery: %@", self, sql);
}
if (shouldCacheStatements) {
... ... @@ -262,15 +280,15 @@
if (!pStmt) {
do {
retry = NO;
rc = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0);
if (SQLITE_BUSY == rc) {
retry = YES;
usleep(20);
if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) {
RMLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
RMLog(@"Database busy");
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
[self setInUse:NO];
return nil;
... ... @@ -280,12 +298,12 @@
if (logsErrors) {
RMLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
RMLog(@"DB Query: %@", sql);
NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
NSLog(@"DB Query: %@", sql);
if (crashOnErrors) {
#ifdef __BIG_ENDIAN__
asm{ trap };
#endif
//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR
// asm{ trap };
//#endif
NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
}
}
... ... @@ -304,10 +322,16 @@
int queryCount = sqlite3_bind_parameter_count(pStmt); // pointed out by Dominic Yu (thanks!)
while (idx < queryCount) {
obj = va_arg(args, id);
if (arrayArgs) {
obj = [arrayArgs objectAtIndex:idx];
}
else {
obj = va_arg(args, id);
}
if (traceExecution) {
RMLog(@"obj: %@", obj);
NSLog(@"obj: %@", obj);
}
idx++;
... ... @@ -316,7 +340,7 @@
}
if (idx != queryCount) {
RMLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
NSLog(@"Error: the bind count is not correct for the # of variables (executeQuery)");
sqlite3_finalize(pStmt);
[self setInUse:NO];
return nil;
... ... @@ -350,14 +374,17 @@
va_list args;
va_start(args, sql);
id result = [self executeQuery:sql arguments:args];
id result = [self executeQuery:sql withArgumentsInArray:nil orVAList:args];
va_end(args);
return result;
}
- (id) executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments {
return [self executeQuery:sql withArgumentsInArray:arguments orVAList:nil];
}
- (BOOL) executeUpdate:(NSString*)sql arguments:(va_list)args {
- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray*)arrayArgs orVAList:(va_list)args {
if (inUse) {
[self compainAboutInUse];
... ... @@ -371,7 +398,7 @@
FMStatement *cachedStmt = 0x00;
if (traceExecution && sql) {
RMLog(@"%@ executeUpdate: %@", self, sql);
NSLog(@"%@ executeUpdate: %@", self, sql);
}
if (shouldCacheStatements) {
... ... @@ -386,14 +413,14 @@
do {
retry = NO;
rc = sqlite3_prepare(db, [sql UTF8String], -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, [sql UTF8String], -1, &pStmt, 0);
if (SQLITE_BUSY == rc) {
retry = YES;
usleep(20);
if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) {
RMLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
RMLog(@"Database busy");
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
NSLog(@"Database busy");
sqlite3_finalize(pStmt);
[self setInUse:NO];
return NO;
... ... @@ -403,12 +430,12 @@
if (logsErrors) {
RMLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
RMLog(@"DB Query: %@", sql);
NSLog(@"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
NSLog(@"DB Query: %@", sql);
if (crashOnErrors) {
#ifdef __BIG_ENDIAN__
asm{ trap };
#endif
//#if defined(__BIG_ENDIAN__) && !TARGET_IPHONE_SIMULATOR
// asm{ trap };
//#endif
NSAssert2(false, @"DB Error: %d \"%@\"", [self lastErrorCode], [self lastErrorMessage]);
}
}
... ... @@ -429,10 +456,16 @@
while (idx < queryCount) {
obj = va_arg(args, id);
if (arrayArgs) {
obj = [arrayArgs objectAtIndex:idx];
}
else {
obj = va_arg(args, id);
}
if (traceExecution) {
RMLog(@"obj: %@", obj);
NSLog(@"obj: %@", obj);
}
idx++;
... ... @@ -441,7 +474,7 @@
}
if (idx != queryCount) {
RMLog(@"Error: the bind count is not correct for the # of variables (%@) (executeUpdate)", sql);
NSLog(@"Error: the bind count is not correct for the # of variables (%@) (executeUpdate)", sql);
sqlite3_finalize(pStmt);
[self setInUse:NO];
return NO;
... ... @@ -462,8 +495,8 @@
usleep(20);
if (busyRetryTimeout && (numberOfRetries++ > busyRetryTimeout)) {
RMLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
RMLog(@"Database busy");
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [self databasePath]);
NSLog(@"Database busy");
retry = NO;
}
}
... ... @@ -471,18 +504,18 @@
// all is well, let's return.
}
else if (SQLITE_ERROR == rc) {
RMLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg(db));
RMLog(@"DB Query: %@", sql);
NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_ERROR", rc, sqlite3_errmsg(db));
NSLog(@"DB Query: %@", sql);
}
else if (SQLITE_MISUSE == rc) {
// uh oh.
RMLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg(db));
RMLog(@"DB Query: %@", sql);
NSLog(@"Error calling sqlite3_step (%d: %s) SQLITE_MISUSE", rc, sqlite3_errmsg(db));
NSLog(@"DB Query: %@", sql);
}
else {
// wtf?
RMLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg(db));
RMLog(@"DB Query: %@", sql);
NSLog(@"Unknown error calling sqlite3_step (%d: %s) eu", rc, sqlite3_errmsg(db));
NSLog(@"DB Query: %@", sql);
}
} while (retry);
... ... @@ -516,11 +549,12 @@
return (rc == SQLITE_OK);
}
- (BOOL) executeUpdate:(NSString*)sql, ... {
va_list args;
va_start(args, sql);
BOOL result = [self executeUpdate:sql arguments:args];
BOOL result = [self executeUpdate:sql withArgumentsInArray:nil orVAList:args];
va_end(args);
return result;
... ... @@ -528,6 +562,16 @@
- (BOOL) executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments {
return [self executeUpdate:sql withArgumentsInArray:arguments orVAList:nil];
}
/*
- (id) executeUpdate:(NSString *)sql arguments:(va_list)args {
}
*/
- (BOOL) rollback {
BOOL b = [self executeUpdate:@"ROLLBACK TRANSACTION;"];
if (b) {
... ...
... ... @@ -10,15 +10,22 @@
@interface FMDatabase (FMDatabaseAdditions)
- (int) intForQuery:(NSString*)objs, ...;
- (long) longForQuery:(NSString*)objs, ...;
- (BOOL) boolForQuery:(NSString*)objs, ...;
- (double) doubleForQuery:(NSString*)objs, ...;
- (NSString*) stringForQuery:(NSString*)objs, ...;
- (NSData*) dataForQuery:(NSString*)objs, ...;
- (int)intForQuery:(NSString*)objs, ...;
- (long)longForQuery:(NSString*)objs, ...;
- (BOOL)boolForQuery:(NSString*)objs, ...;
- (double)doubleForQuery:(NSString*)objs, ...;
- (NSString*)stringForQuery:(NSString*)objs, ...;
- (NSData*)dataForQuery:(NSString*)objs, ...;
- (NSDate*)dateForQuery:(NSString*)objs, ...;
// Notice that there's no dataNoCopyForQuery:.
// That would be a bad idea, because we close out the result set, and then what
// happens to the data that we just didn't copy? Who knows, not I.
- (BOOL)tableExists:(NSString*)tableName;
- (FMResultSet*)getSchema;
- (FMResultSet*)getTableSchema:(NSString*)tableName;
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName;
@end
... ...
... ... @@ -14,7 +14,7 @@
#define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \
va_list args; \
va_start(args, query); \
FMResultSet *resultSet = [self executeQuery:query arguments:args]; \
FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orVAList:args]; \
va_end(args); \
if (![resultSet next]) { return (type)0; } \
type ret = [resultSet sel:0]; \
... ... @@ -47,5 +47,68 @@ return ret;
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex);
}
- (NSDate*)dateForQuery:(NSString*)query, ...; {
RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex);
}
//check if table exist in database (patch from OZLB)
- (BOOL)tableExists:(NSString*)tableName {
BOOL returnBool;
//lower case table name
tableName = [tableName lowercaseString];
//search in sqlite_master table if table exists
FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName];
//if at least one next exists, table exists
returnBool = [rs next];
//close and free object
[rs close];
return returnBool;
}
//get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
//check if table exist in database (patch from OZLB)
- (FMResultSet*)getSchema {
//result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING]
FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"];
return rs;
}
//get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
- (FMResultSet*)getTableSchema:(NSString*)tableName {
//result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER]
FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info(%@)", tableName]];
return rs;
}
//check if column exist in table
- (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName {
BOOL returnBool = NO;
//lower case table name
tableName = [tableName lowercaseString];
//lower case column name
columnName = [columnName lowercaseString];
//get table schema
FMResultSet *rs = [self getTableSchema: tableName];
//check if column is present in table schema
while ([rs next]) {
if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString: columnName]) {
returnBool = YES;
break;
}
}
//close and free object
[rs close];
return returnBool;
}
@end
... ...
... ... @@ -27,6 +27,10 @@
- (void)setParentDB:(FMDatabase *)newDb;
- (BOOL) next;
- (BOOL) hasAnotherRow;
- (int) columnIndexForName:(NSString*)columnName;
- (NSString*) columnNameForIndex:(int)columnIdx;
- (int) intForColumn:(NSString*)columnName;
- (int) intForColumnIndex:(int)columnIdx;
... ... @@ -52,6 +56,9 @@
- (NSData*) dataForColumn:(NSString*)columnName;
- (NSData*) dataForColumnIndex:(int)columnIdx;
- (const unsigned char *) UTF8StringForColumnIndex:(int)columnIdx;
- (const unsigned char *) UTF8StringForColumnName:(NSString*)columnName;
/*
If you are going to use this data after you iterate over the next row, or after you close the
result set, make sure to make a copy of the data first (or just use dataForColumn:/dataForColumnIndex:)
... ... @@ -60,6 +67,9 @@ If you don't, you're going to be in a world of hurt when you try and use the dat
- (NSData*) dataNoCopyForColumn:(NSString*)columnName;
- (NSData*) dataNoCopyForColumnIndex:(int)columnIdx;
- (BOOL) columnIndexIsNull:(int)columnIdx;
- (BOOL) columnIsNull:(NSString*)columnName;
- (void) kvcMagic:(id)object;
@end
... ...
... ... @@ -60,13 +60,11 @@
- (void) kvcMagic:(id)object {
int columnCount = sqlite3_column_count(statement.statement);
int columnIdx = 0;
for (columnIdx = 0; columnIdx < columnCount; columnIdx++) {
const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx);
// check for a null row
... ... @@ -96,8 +94,8 @@
if ([parentDB busyRetryTimeout] && (numberOfRetries++ > [parentDB busyRetryTimeout])) {
RMLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]);
RMLog(@"Database busy");
NSLog(@"%s:%d Database busy (%@)", __FUNCTION__, __LINE__, [parentDB databasePath]);
NSLog(@"Database busy");
break;
}
}
... ... @@ -105,17 +103,17 @@
// all is well, let's return.
}
else if (SQLITE_ERROR == rc) {
RMLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
break;
}
else if (SQLITE_MISUSE == rc) {
// uh oh.
RMLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
NSLog(@"Error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
break;
}
else {
// wtf?
RMLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
NSLog(@"Unknown error calling sqlite3_step (%d: %s) rs", rc, sqlite3_errmsg([parentDB sqliteHandle]));
break;
}
... ... @@ -129,6 +127,10 @@
return (rc == SQLITE_ROW);
}
- (BOOL) hasAnotherRow {
return sqlite3_errcode([parentDB sqliteHandle]) == SQLITE_ROW;
}
- (int) columnIndexForName:(NSString*)columnName {
if (!columnNamesSetup) {
... ... @@ -143,7 +145,7 @@
return [n intValue];
}
RMLog(@"Warning: I could not find the column named '%@'.", columnName);
NSLog(@"Warning: I could not find the column named '%@'.", columnName);
return -1;
}
... ... @@ -151,36 +153,15 @@
- (int) intForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return 0;
}
return sqlite3_column_int(statement.statement, columnIdx);
return [self intForColumnIndex:[self columnIndexForName:columnName]];
}
- (int) intForColumnIndex:(int)columnIdx {
return sqlite3_column_int(statement.statement, columnIdx);
}
- (long) longForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return 0;
}
return (long)sqlite3_column_int64(statement.statement, columnIdx);
return [self longForColumnIndex:[self columnIndexForName:columnName]];
}
- (long) longForColumnIndex:(int)columnIdx {
... ... @@ -188,18 +169,7 @@
}
- (long long int) longLongIntForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return 0;
}
return sqlite3_column_int64(statement.statement, columnIdx);
return [self longLongIntForColumnIndex:[self columnIndexForName:columnName]];
}
- (long long int) longLongIntForColumnIndex:(int)columnIdx {
... ... @@ -207,7 +177,7 @@
}
- (BOOL) boolForColumn:(NSString*)columnName {
return ([self intForColumn:columnName] != 0);
return [self boolForColumnIndex:[self columnIndexForName:columnName]];
}
- (BOOL) boolForColumnIndex:(int)columnIdx {
... ... @@ -215,29 +185,19 @@
}
- (double) doubleForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return 0;
}
return sqlite3_column_double(statement.statement, columnIdx);
return [self doubleForColumnIndex:[self columnIndexForName:columnName]];
}
- (double) doubleForColumnIndex:(int)columnIdx {
return sqlite3_column_double(statement.statement, columnIdx);
}
#pragma mark string functions
- (NSString*) stringForColumnIndex:(int)columnIdx {
if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
const char *c = (const char *)sqlite3_column_text(statement.statement, columnIdx);
if (!c) {
... ... @@ -249,61 +209,33 @@
}
- (NSString*) stringForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return nil;
}
return [self stringForColumnIndex:columnIdx];
return [self stringForColumnIndex:[self columnIndexForName:columnName]];
}
- (NSDate*) dateForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return nil;
}
return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumn:columnName]];
return [self dateForColumnIndex:[self columnIndexForName:columnName]];
}
- (NSDate*) dateForColumnIndex:(int)columnIdx {
if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
return [NSDate dateWithTimeIntervalSince1970:[self doubleForColumnIndex:columnIdx]];
}
- (NSData*) dataForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return nil;
}
return [self dataForColumnIndex:columnIdx];
return [self dataForColumnIndex:[self columnIndexForName:columnName]];
}
- (NSData*) dataForColumnIndex:(int)columnIdx {
if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
int dataSize = sqlite3_column_bytes(statement.statement, columnIdx);
NSMutableData *data = [NSMutableData dataWithLength:dataSize];
... ... @@ -315,23 +247,15 @@
- (NSData*) dataNoCopyForColumn:(NSString*)columnName {
if (!columnNamesSetup) {
[self setupColumnNames];
}
int columnIdx = [self columnIndexForName:columnName];
if (columnIdx == -1) {
return nil;
}
return [self dataNoCopyForColumnIndex:columnIdx];
return [self dataNoCopyForColumnIndex:[self columnIndexForName:columnName]];
}
- (NSData*) dataNoCopyForColumnIndex:(int)columnIdx {
if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
int dataSize = sqlite3_column_bytes(statement.statement, columnIdx);
NSData *data = [NSData dataWithBytesNoCopy:(void *)sqlite3_column_blob(statement.statement, columnIdx) length:dataSize freeWhenDone:NO];
... ... @@ -340,8 +264,32 @@
}
- (BOOL) columnIndexIsNull:(int)columnIdx {
return sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL;
}
- (BOOL) columnIsNull:(NSString*)columnName {
return [self columnIndexIsNull:[self columnIndexForName:columnName]];
}
- (const unsigned char *) UTF8StringForColumnIndex:(int)columnIdx {
if (sqlite3_column_type(statement.statement, columnIdx) == SQLITE_NULL || (columnIdx < 0)) {
return nil;
}
return sqlite3_column_text(statement.statement, columnIdx);
}
- (const unsigned char *) UTF8StringForColumnName:(NSString*)columnName {
return [self UTF8StringForColumnIndex:[self columnIndexForName:columnName]];
}
// returns autoreleased NSString containing the name of the column in the result set
- (NSString*) columnNameForIndex:(int)columnIdx {
return [NSString stringWithUTF8String: sqlite3_column_name(statement.statement, columnIdx)];
}
- (void)setParentDB:(FMDatabase *)newDb {
parentDB = newDb;
... ...
... ... @@ -2,6 +2,8 @@
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
#define FMDBQuickCheck(SomeBool) { if (!(SomeBool)) { NSLog(@"Failure on line %d", __LINE__); return 123; } }
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
... ... @@ -11,7 +13,7 @@ int main (int argc, const char * argv[]) {
FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
if (![db open]) {
RMLog(@"Could not open db.");
NSLog(@"Could not open db.");
[pool release];
return 0;
}
... ... @@ -21,8 +23,11 @@ int main (int argc, const char * argv[]) {
// create a bad statement, just to test the error code.
[db executeUpdate:@"blah blah blah"];
FMDBQuickCheck([db hadError]);
if ([db hadError]) {
RMLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
}
// but of course, I don't bother checking the error codes below.
... ... @@ -65,7 +70,7 @@ int main (int argc, const char * argv[]) {
FMResultSet *rs = [db executeQuery:@"select rowid,* from test where a = ?", @"hi'"];
while ([rs next]) {
// just print out what we've got in a number of formats.
RMLog(@"%d %@ %@ %@ %@ %f %f",
NSLog(@"%d %@ %@ %@ %@ %f %f",
[rs intForColumn:@"c"],
[rs stringForColumn:@"b"],
[rs stringForColumn:@"a"],
... ... @@ -73,6 +78,14 @@ int main (int argc, const char * argv[]) {
[rs dateForColumn:@"d"],
[rs doubleForColumn:@"d"],
[rs doubleForColumn:@"e"]);
if (!([[rs columnNameForIndex:0] isEqualToString:@"rowid"] &&
[[rs columnNameForIndex:1] isEqualToString:@"a"])
) {
NSLog(@"WHOA THERE BUDDY, columnNameForIndex ISN'T WORKING!");
return 7;
}
}
// close the result set.
// it'll also close when it's dealloc'd, but we're closing the database before
... ... @@ -84,32 +97,32 @@ int main (int argc, const char * argv[]) {
[db executeUpdate:@"create table blobTable (a text, b blob)"];
// let's read in an image from safari's app bundle.
NSData *d = [NSData dataWithContentsOfFile:@"/Applications/Safari.app/Contents/Resources/compass.icns"];
if (d) {
[db executeUpdate:@"insert into blobTable (a, b) values (?,?)", @"safari's compass", d];
NSData *safariCompass = [NSData dataWithContentsOfFile:@"/Applications/Safari.app/Contents/Resources/compass.icns"];
if (safariCompass) {
[db executeUpdate:@"insert into blobTable (a, b) values (?,?)", @"safari's compass", safariCompass];
rs = [db executeQuery:@"select b from blobTable where a = ?", @"safari's compass"];
if ([rs next]) {
d = [rs dataForColumn:@"b"];
[d writeToFile:@"/tmp/compass.icns" atomically:NO];
safariCompass = [rs dataForColumn:@"b"];
[safariCompass writeToFile:@"/tmp/compass.icns" atomically:NO];
// let's look at our fancy image that we just wrote out..
system("/usr/bin/open /tmp/compass.icns");
// ye shall read the header for this function, or suffer the consequences.
d = [rs dataNoCopyForColumn:@"b"];
[d writeToFile:@"/tmp/compass_data_no_copy.icns" atomically:NO];
safariCompass = [rs dataNoCopyForColumn:@"b"];
[safariCompass writeToFile:@"/tmp/compass_data_no_copy.icns" atomically:NO];
system("/usr/bin/open /tmp/compass_data_no_copy.icns");
}
else {
RMLog(@"Could not select image.");
NSLog(@"Could not select image.");
}
[rs close];
}
else {
RMLog(@"Can't find compass image..");
NSLog(@"Can't find compass image..");
}
... ... @@ -118,7 +131,7 @@ int main (int argc, const char * argv[]) {
[db executeUpdate:@"insert into t1 values (?)", [NSNumber numberWithInt:5]];
int a = [db intForQuery:@"select a from t1 where a = ?", [NSNumber numberWithInt:5]];
if (a != 5) {
RMLog(@"intForQuery didn't work (a != 5)");
NSLog(@"intForQuery didn't work (a != 5)");
}
// test the busy rety timeout schtuff.
... ... @@ -131,16 +144,16 @@ int main (int argc, const char * argv[]) {
rs = [newDb executeQuery:@"select rowid,* from test where a = ?", @"hi'"];
[rs next]; // just grab one... which will keep the db locked.
RMLog(@"Testing the busy timeout");
NSLog(@"Testing the busy timeout");
BOOL success = [db executeUpdate:@"insert into t1 values (5)"];
if (success) {
RMLog(@"Whoa- the database didn't stay locked!");
NSLog(@"Whoa- the database didn't stay locked!");
return 7;
}
else {
RMLog(@"Hurray, our timeout worked");
NSLog(@"Hurray, our timeout worked");
}
[rs close];
... ... @@ -148,11 +161,11 @@ int main (int argc, const char * argv[]) {
success = [db executeUpdate:@"insert into t1 values (5)"];
if (!success) {
RMLog(@"Whoa- the database shouldn't be locked!");
NSLog(@"Whoa- the database shouldn't be locked!");
return 8;
}
else {
RMLog(@"Hurray, we can insert again!");
NSLog(@"Hurray, we can insert again!");
}
... ... @@ -161,7 +174,7 @@ int main (int argc, const char * argv[]) {
[db executeUpdate:@"create table t2 (a integer, b integer)"];
if (![db executeUpdate:@"insert into t2 values (?, ?)", nil, [NSNumber numberWithInt:5]]) {
RMLog(@"UH OH, can't insert a nil value for some reason...");
NSLog(@"UH OH, can't insert a nil value for some reason...");
}
... ... @@ -173,17 +186,17 @@ int main (int argc, const char * argv[]) {
NSString *b = [rs stringForColumnIndex:1];
if (a != nil) {
RMLog(@"%s:%d", __FUNCTION__, __LINE__);
RMLog(@"OH OH, PROBLEMO!");
NSLog(@"%s:%d", __FUNCTION__, __LINE__);
NSLog(@"OH OH, PROBLEMO!");
return 10;
}
else {
RMLog(@"YAY, NULL VALUES");
NSLog(@"YAY, NULL VALUES");
}
if (![b isEqualToString:@"5"]) {
RMLog(@"%s:%d", __FUNCTION__, __LINE__);
RMLog(@"OH OH, PROBLEMO!");
NSLog(@"%s:%d", __FUNCTION__, __LINE__);
NSLog(@"OH OH, PROBLEMO!");
return 10;
}
}
... ... @@ -225,7 +238,7 @@ int main (int argc, const char * argv[]) {
[rs2 next];
if ([rs2 intForColumnIndex:0] != newVal) {
RMLog(@"Oh crap, our update didn't work out!");
NSLog(@"Oh crap, our update didn't work out!");
return 9;
}
... ... @@ -247,19 +260,222 @@ int main (int argc, const char * argv[]) {
NSString *b = [rs stringForColumnIndex:1];
if (!b) {
RMLog(@"Oh crap, the nil / null inserts didn't work!");
NSLog(@"Oh crap, the nil / null inserts didn't work!");
return 10;
}
if (a) {
RMLog(@"Oh crap, the nil / null inserts didn't work (son of error message)!");
NSLog(@"Oh crap, the nil / null inserts didn't work (son of error message)!");
return 11;
}
else {
RMLog(@"HURRAH FOR NSNULL (and nil)!");
NSLog(@"HURRAH FOR NSNULL (and nil)!");
}
}
// null dates
NSDate *date = [NSDate date];
[db executeUpdate:@"create table datetest (a double, b double, c double)"];
[db executeUpdate:@"insert into datetest (a, b, c) values (?, ?, 0)" , [NSNull null], date];
rs = [db executeQuery:@"select * from datetest"];
while ([rs next]) {
NSDate *a = [rs dateForColumnIndex:0];
NSDate *b = [rs dateForColumnIndex:1];
NSDate *c = [rs dateForColumnIndex:2];
if (a) {
NSLog(@"Oh crap, the null date insert didn't work!");
return 12;
}
if (!c) {
NSLog(@"Oh crap, the 0 date insert didn't work!");
return 12;
}
NSTimeInterval dti = fabs([b timeIntervalSinceDate:date]);
if (floor(dti) > 0.0) {
NSLog(@"Date matches didn't really happen... time difference of %f", dti);
return 13;
}
dti = fabs([c timeIntervalSinceDate:[NSDate dateWithTimeIntervalSince1970:0]]);
if (floor(dti) > 0.0) {
NSLog(@"Date matches didn't really happen... time difference of %f", dti);
return 13;
}
}
NSDate *foo = [db dateForQuery:@"select b from datetest where c = 0"];
assert(foo);
NSTimeInterval dti = fabs([foo timeIntervalSinceDate:date]);
if (floor(dti) > 0.0) {
NSLog(@"Date matches didn't really happen... time difference of %f", dti);
return 14;
}
[db executeUpdate:@"create table nulltest2 (s text, d data, i integer, f double, b integer)"];
[db executeUpdate:@"insert into nulltest2 (s, d, i, f, b) values (?, ?, ?, ?, ?)" , @"Hi", safariCompass, [NSNumber numberWithInt:12], [NSNumber numberWithFloat:4.4], [NSNumber numberWithBool:YES]];
[db executeUpdate:@"insert into nulltest2 (s, d, i, f, b) values (?, ?, ?, ?, ?)" , nil, nil, nil, nil, [NSNull null]];
rs = [db executeQuery:@"select * from nulltest2"];
while ([rs next]) {
int i = [rs intForColumnIndex:2];
if (i == 12) {
// it's the first row we inserted.
FMDBQuickCheck(![rs columnIndexIsNull:0]);
FMDBQuickCheck(![rs columnIndexIsNull:1]);
FMDBQuickCheck(![rs columnIndexIsNull:2]);
FMDBQuickCheck(![rs columnIndexIsNull:3]);
FMDBQuickCheck(![rs columnIndexIsNull:4]);
FMDBQuickCheck( [rs columnIndexIsNull:5]);
FMDBQuickCheck([[rs dataForColumn:@"d"] length] == [safariCompass length]);
FMDBQuickCheck(![rs dataForColumn:@"notthere"]);
FMDBQuickCheck(![rs stringForColumnIndex:-2]);
FMDBQuickCheck([rs boolForColumnIndex:4]);
FMDBQuickCheck([rs boolForColumn:@"b"]);
FMDBQuickCheck(fabs(4.4 - [rs doubleForColumn:@"f"]) < 0.0000001);
FMDBQuickCheck(12 == [rs intForColumn:@"i"]);
FMDBQuickCheck(12 == [rs intForColumnIndex:2]);
FMDBQuickCheck(0 == [rs intForColumnIndex:12]); // there is no 12
FMDBQuickCheck(0 == [rs intForColumn:@"notthere"]);
FMDBQuickCheck(12 == [rs longForColumn:@"i"]);
FMDBQuickCheck(12 == [rs longLongIntForColumn:@"i"]);
}
else {
// let's test various null things.
FMDBQuickCheck([rs columnIndexIsNull:0]);
FMDBQuickCheck([rs columnIndexIsNull:1]);
FMDBQuickCheck([rs columnIndexIsNull:2]);
FMDBQuickCheck([rs columnIndexIsNull:3]);
FMDBQuickCheck([rs columnIndexIsNull:4]);
FMDBQuickCheck([rs columnIndexIsNull:5]);
FMDBQuickCheck(![rs dataForColumn:@"d"]);
}
}
{
[db executeUpdate:@"create table testOneHundredTwelvePointTwo (a text, b integer)"];
[db executeUpdate:@"insert into testOneHundredTwelvePointTwo values (?, ?)" withArgumentsInArray:[NSArray arrayWithObjects:@"one", [NSNumber numberWithInteger:2], nil]];
[db executeUpdate:@"insert into testOneHundredTwelvePointTwo values (?, ?)" withArgumentsInArray:[NSArray arrayWithObjects:@"one", [NSNumber numberWithInteger:3], nil]];
rs = [db executeQuery:@"select * from testOneHundredTwelvePointTwo where b > ?" withArgumentsInArray:[NSArray arrayWithObject:[NSNumber numberWithInteger:1]]];
FMDBQuickCheck([rs next]);
FMDBQuickCheck([rs hasAnotherRow]);
FMDBQuickCheck(![db hadError]);
FMDBQuickCheck([[rs stringForColumnIndex:0] isEqualToString:@"one"]);
FMDBQuickCheck([rs intForColumnIndex:1] == 2);
FMDBQuickCheck([rs next]);
FMDBQuickCheck([rs intForColumnIndex:1] == 3);
FMDBQuickCheck(![rs next]);
FMDBQuickCheck(![rs hasAnotherRow]);
}
{
FMDBQuickCheck([db executeUpdate:@"create table t4 (a text, b text)"]);
FMDBQuickCheck(([db executeUpdate:@"insert into t4 (a, b) values (?, ?)", @"one", @"two"]));
rs = [db executeQuery:@"select t4.a as 't4.a', t4.b from t4;"];
FMDBQuickCheck((rs != nil));
[rs next];
FMDBQuickCheck([[rs stringForColumn:@"t4.a"] isEqualToString:@"one"]);
FMDBQuickCheck([[rs stringForColumn:@"b"] isEqualToString:@"two"]);
FMDBQuickCheck(strcmp((const char*)[rs UTF8StringForColumnName:@"b"], "two") == 0);
[rs close];
// let's try these again, with the withArgumentsInArray: variation
FMDBQuickCheck([db executeUpdate:@"drop table t4;" withArgumentsInArray:[NSArray array]]);
FMDBQuickCheck([db executeUpdate:@"create table t4 (a text, b text)" withArgumentsInArray:[NSArray array]]);
FMDBQuickCheck(([db executeUpdate:@"insert into t4 (a, b) values (?, ?)" withArgumentsInArray:[NSArray arrayWithObjects:@"one", @"two", nil]]));
rs = [db executeQuery:@"select t4.a as 't4.a', t4.b from t4;" withArgumentsInArray:[NSArray array]];
FMDBQuickCheck((rs != nil));
[rs next];
FMDBQuickCheck([[rs stringForColumn:@"t4.a"] isEqualToString:@"one"]);
FMDBQuickCheck([[rs stringForColumn:@"b"] isEqualToString:@"two"]);
FMDBQuickCheck(strcmp((const char*)[rs UTF8StringForColumnName:@"b"], "two") == 0);
[rs close];
}
{
FMDBQuickCheck([db tableExists:@"t4"]);
FMDBQuickCheck(![db tableExists:@"thisdoesntexist"]);
rs = [db getSchema];
while ([rs next]) {
FMDBQuickCheck([[rs stringForColumn:@"type"] isEqualToString:@"table"]);
}
}
// just for fun.
rs = [db executeQuery:@"PRAGMA database_list"];
while ([rs next]) {
NSString *file = [rs stringForColumn:@"file"];
NSLog(@"database_list: %@", file);
}
// print out some stats if we are using cached statements.
if ([db shouldCacheStatements]) {
... ... @@ -267,10 +483,10 @@ int main (int argc, const char * argv[]) {
FMStatement *statement;
while ((statement = [e nextObject])) {
RMLog(@"%@", statement);
NSLog(@"%@", statement);
}
}
RMLog(@"That was version %@ of sqlite", [FMDatabase sqliteLibVersion]);
NSLog(@"That was version %@ of sqlite", [FMDatabase sqliteLibVersion]);
[db close];
... ...
... ... @@ -126,8 +126,7 @@ enum {
/// zoom level is clamped to range (minZoom, maxZoom)
@property (readwrite) float zoom;
@property (readwrite) float minZoom;
@property (readwrite) float maxZoom;
@property (nonatomic, readwrite) float minZoom, maxZoom;
@property (readonly) RMTileImageSet *imagesOnScreen;
@property (readonly) RMTileLoader *tileLoader;
... ...
... ... @@ -24,7 +24,7 @@
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#import "RMGlobalConstants.h"w
#import "RMGlobalConstants.h"
#import "RMTileLoader.h"
#import "RMTileImage.h"
... ...
... ... @@ -35,11 +35,10 @@
{
[self setMaxZoom:_maxZoom];
[self setMinZoom:_minZoom];
host = _host;
key = _key;
}
host = _host;
key = _key;
return self;
}
... ...
... ... @@ -1198,7 +1198,7 @@
OTHER_LDFLAGS = "";
PREBINDING = NO;
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphonesimulator3.0;
SDKROOT = iphonesimulator3.2;
};
name = Debug;
};
... ... @@ -1215,7 +1215,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
OTHER_LDFLAGS = "";
PREBINDING = NO;
SDKROOT = iphoneos3.0;
SDKROOT = iphonesimulator3.2;
};
name = Release;
};
... ...
... ... @@ -9,9 +9,9 @@
#endif
#if DEBUG
#define RMLog(args...) NSLog( @"%@", [NSString stringWithFormat: args])
#define LogMethod() NSLog(@"%s logged method call: -[%@ %s] (line %d)", _cmd, self, _cmd, __LINE__)
#define WarnDeprecated() NSLog(@"***** WARNING: %s deprecated method call: -[%@ %s] (line %d)", _cmd, self, _cmd, __LINE__)
#define RMLog(args...) NSLog(@"%@", [NSString stringWithFormat: args])
#define LogMethod() NSLog(@"logged method call: -[%@ %@] (line %d)", self, NSStringFromSelector(_cmd), __LINE__)
#define WarnDeprecated() NSLog(@"***** WARNING: deprecated method call: -[%@ %@] (line %d)", self, NSStringFromSelector(_cmd), __LINE__)
#else
// DEBUG not defined:
... ...