Browse Source

Merge pull request #621 from robertmryan/master

Fix isOpen logic
August "Gus" Mueller 8 years ago
parent
commit
efcfb3cc79
3 changed files with 73 additions and 5 deletions
  1. 44 0
      Tests/FMDatabaseTests.m
  2. 4 0
      src/fmdb/FMDatabase.h
  3. 25 5
      src/fmdb/FMDatabase.m

+ 44 - 0
Tests/FMDatabaseTests.m

@@ -1486,4 +1486,48 @@ - (void)testImmediateTransaction {
     XCTAssertEqualObjects([db lastError].localizedDescription, @"cannot start a transaction within a transaction");
     XCTAssertEqualObjects([db lastError].localizedDescription, @"cannot start a transaction within a transaction");
 }
 }
 
 
+- (void)testOpenFailure {
+    NSURL *tempURL = [NSURL fileURLWithPath:NSTemporaryDirectory()];
+    NSURL *fileURL1 = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+    NSURL *fileURL2 = [tempURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
+    NSFileManager *manager = [NSFileManager defaultManager];
+    
+    // ok, first create one database
+    
+    FMDatabase *db = [FMDatabase databaseWithURL:fileURL1];
+    BOOL success = [db open];
+    XCTAssert(success, @"Database not created correctly for purposes of test");
+    success = [db executeUpdate:@"create table if not exists foo (bar text)"];
+    XCTAssert(success, @"Table created correctly for purposes of test");
+    [db close];
+    
+    // now, try to create open second database even though it doesn't exist
+    
+    db = [FMDatabase databaseWithURL:fileURL2];
+    success = [db openWithFlags:SQLITE_OPEN_READWRITE];
+    XCTAssert(!success, @"Opening second database file that doesn't exist should not have succeeded");
+    
+    // OK, everything so far is fine, opening a db without CREATE option above should have failed,
+    // but so fix the missing file issue and re-opening
+    
+    success = [manager copyItemAtURL:fileURL1 toURL:fileURL2 error:nil];
+    XCTAssert(success, @"Copying of db should have succeeded");
+    
+    // now let's try opening it again
+    
+    success = [db openWithFlags:SQLITE_OPEN_READWRITE];
+    XCTAssert(success, @"Opening second database should now succeed");
+
+    // now let's try using it
+    FMResultSet *rs = [db executeQuery:@"select * from foo"];
+    XCTAssertNotNil(rs, @"Should successfully be able to use re-opened database");
+    
+    // let's clean up
+    
+    [rs close];
+    [db close];
+    [manager removeItemAtURL:fileURL1 error:nil];
+    [manager removeItemAtURL:fileURL2 error:nil];
+}
+
 @end
 @end

+ 4 - 0
src/fmdb/FMDatabase.h

@@ -221,6 +221,10 @@ typedef NS_ENUM(int, FMDBCheckpointMode) {
 /// @name Opening and closing database
 /// @name Opening and closing database
 ///-----------------------------------
 ///-----------------------------------
 
 
+/// Is the database open or not?
+
+@property (nonatomic) BOOL isOpen;
+
 /** Opening a new database connection
 /** Opening a new database connection
  
  
  The database is opened for reading and writing, and is created if it does not already exist.
  The database is opened for reading and writing, and is created if it does not already exist.

+ 25 - 5
src/fmdb/FMDatabase.m

@@ -68,6 +68,7 @@ - (instancetype)initWithPath:(NSString *)path {
         _logsErrors                 = YES;
         _logsErrors                 = YES;
         _crashOnErrors              = NO;
         _crashOnErrors              = NO;
         _maxBusyRetryTimeInterval   = 2;
         _maxBusyRetryTimeInterval   = 2;
+        _isOpen                     = NO;
     }
     }
     
     
     return self;
     return self;
@@ -160,10 +161,18 @@ - (const char*)sqlitePath {
 #pragma mark Open and close database
 #pragma mark Open and close database
 
 
 - (BOOL)open {
 - (BOOL)open {
-    if (_db) {
+    if (_isOpen) {
         return YES;
         return YES;
     }
     }
     
     
+    // if we previously tried to open and it failed, make sure to close it before we try again
+    
+    if (_db) {
+        [self close];
+    }
+    
+    // now open database
+
     int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db );
     int err = sqlite3_open([self sqlitePath], (sqlite3**)&_db );
     if(err != SQLITE_OK) {
     if(err != SQLITE_OK) {
         NSLog(@"error opening!: %d", err);
         NSLog(@"error opening!: %d", err);
@@ -175,6 +184,7 @@ - (BOOL)open {
         [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
         [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
     }
     }
     
     
+    _isOpen = YES;
     
     
     return YES;
     return YES;
 }
 }
@@ -182,12 +192,21 @@ - (BOOL)open {
 - (BOOL)openWithFlags:(int)flags {
 - (BOOL)openWithFlags:(int)flags {
     return [self openWithFlags:flags vfs:nil];
     return [self openWithFlags:flags vfs:nil];
 }
 }
+
 - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
 - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
 #if SQLITE_VERSION_NUMBER >= 3005000
 #if SQLITE_VERSION_NUMBER >= 3005000
-    if (_db) {
+    if (_isOpen) {
         return YES;
         return YES;
     }
     }
     
     
+    // if we previously tried to open and it failed, make sure to close it before we try again
+    
+    if (_db) {
+        [self close];
+    }
+    
+    // now open database
+    
     int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]);
     int err = sqlite3_open_v2([self sqlitePath], (sqlite3**)&_db, flags, [vfsName UTF8String]);
     if(err != SQLITE_OK) {
     if(err != SQLITE_OK) {
         NSLog(@"error opening!: %d", err);
         NSLog(@"error opening!: %d", err);
@@ -199,6 +218,8 @@ - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
         [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
         [self setMaxBusyRetryTimeInterval:_maxBusyRetryTimeInterval];
     }
     }
     
     
+    _isOpen = YES;
+    
     return YES;
     return YES;
 #else
 #else
     NSLog(@"openWithFlags requires SQLite 3.5");
     NSLog(@"openWithFlags requires SQLite 3.5");
@@ -206,7 +227,6 @@ - (BOOL)openWithFlags:(int)flags vfs:(NSString *)vfsName {
 #endif
 #endif
 }
 }
 
 
-
 - (BOOL)close {
 - (BOOL)close {
     
     
     [self clearCachedStatements];
     [self clearCachedStatements];
@@ -466,7 +486,7 @@ - (NSString *)stringFromDate:(NSDate *)date {
 
 
 - (BOOL)goodConnection {
 - (BOOL)goodConnection {
     
     
-    if (!_db) {
+    if (!_isOpen) {
         return NO;
         return NO;
     }
     }
     
     
@@ -493,7 +513,7 @@ - (void)warnInUse {
 
 
 - (BOOL)databaseExists {
 - (BOOL)databaseExists {
     
     
-    if (!_db) {
+    if (!_isOpen) {
         
         
         NSLog(@"The FMDatabase %@ is not open.", self);
         NSLog(@"The FMDatabase %@ is not open.", self);