Browse Source

Closing a database now closes all open resultsets

Dave DeLong 14 years ago
parent
commit
ae8622d5b0
3 changed files with 33 additions and 1 deletions
  1. 2 0
      src/FMDatabase.h
  2. 25 0
      src/FMDatabase.m
  3. 6 1
      src/FMResultSet.m

+ 2 - 0
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;

+ 25 - 0
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;
     

+ 6 - 1
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;
 }