diff --git a/src/FMDatabase.h b/src/FMDatabase.h index f1a87259..f125d61a 100644 --- a/src/FMDatabase.h +++ b/src/FMDatabase.h @@ -15,6 +15,7 @@ int busyRetryTimeout; BOOL shouldCacheStatements; NSMutableDictionary *cachedStatements; + NSMutableSet *openResultSets; } @@ -28,6 +29,7 @@ - (BOOL)close; - (BOOL)goodConnection; - (void)clearCachedStatements; +- (void)closeOpenResultSets; // encryption methods. You need to have purchased the sqlite encryption extensions for these to work. - (BOOL)setKey:(NSString*)key; diff --git a/src/FMDatabase.m b/src/FMDatabase.m index 3480a819..46d963b5 100644 --- a/src/FMDatabase.m +++ b/src/FMDatabase.m @@ -12,6 +12,7 @@ - (id)initWithPath:(NSString*)aPath { if (self) { databasePath = [aPath copy]; + openResultSets = [[NSMutableSet alloc] init]; db = 0x00; logsErrors = 0x00; crashOnErrors = 0x00; @@ -29,6 +30,7 @@ - (void)finalize { - (void)dealloc { [self close]; + [openResultSets release]; [cachedStatements release]; [databasePath release]; @@ -76,6 +78,7 @@ - (BOOL)openWithFlags:(int)flags { - (BOOL)close { [self clearCachedStatements]; + [self closeOpenResultSets]; if (!db) { return YES; @@ -118,6 +121,26 @@ - (void)clearCachedStatements { [cachedStatements removeAllObjects]; } +- (void)closeOpenResultSets { + //Copy the set so we don't get mutation errors + NSSet *resultSets = [[openResultSets copy] autorelease]; + + NSEnumerator *e = [resultSets objectEnumerator]; + NSValue *returnedResultSet = nil; + + while((returnedResultSet = [e nextObject])) { + FMResultSet *rs = (FMResultSet *)[returnedResultSet pointerValue]; + if ([rs respondsToSelector:@selector(close)]) { + [rs close]; + } + } +} + +- (void)resultSetDidClose:(FMResultSet *)resultSet { + NSValue *setValue = [NSValue valueWithNonretainedObject:resultSet]; + [openResultSets removeObject:setValue]; +} + - (FMStatement*)cachedStatementForQuery:(NSString*)query { return [cachedStatements objectForKey:query]; } @@ -383,6 +406,8 @@ - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arr // the statement gets closed in rs's dealloc or [rs close]; rs = [FMResultSet resultSetWithStatement:statement usingParentDatabase:self]; [rs setQuery:sql]; + NSValue *openResultSet = [NSValue valueWithNonretainedObject:rs]; + [openResultSets addObject:openResultSet]; statement.useCount = statement.useCount + 1; diff --git a/src/FMResultSet.m b/src/FMResultSet.m index d0cdfc28..138aa14c 100644 --- a/src/FMResultSet.m +++ b/src/FMResultSet.m @@ -2,6 +2,11 @@ #import "FMDatabase.h" #import "unistd.h" +@interface FMDatabase () +- (void)resultSetDidClose:(FMResultSet *)resultSet; +@end + + @interface FMResultSet (Private) - (NSMutableDictionary *)columnNameToIndexMap; - (void)setColumnNameToIndexMap:(NSMutableDictionary *)value; @@ -37,13 +42,13 @@ - (void)dealloc { } - (void)close { - [statement reset]; [statement release]; statement = nil; // we don't need this anymore... (i think) //[parentDB setInUse:NO]; + [parentDB resultSetDidClose:self]; parentDB = nil; }