Database is not open message

735 views
Skip to first unread message

Brett

unread,
Apr 3, 2012, 1:42:34 AM4/3/12
to FMDB
I'm using FMDB in a project I'm working on at the moment.

I have a DatabaseController class that has a FMDatabase property

@interface DatabaseController : NSObject
{
}
@property (strong, nonatomic) FMDatabase *database;

+(DatabaseController *)sharedInstance;

// Other misc methods
@end


The shared instance method uses blocks to assure its only ever created
once. This seems to be the best way to do it under iOS 5.

+ (DatabaseController *)sharedInstance {
static DatabaseController *sharedInstance = nil;
static dispatch_once_t onceToken;

if(sharedInstance) return sharedInstance;

dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}


The init method is as follows

- (id)init {
self = [super init];
if (self) {
[self initialiseDatabase];
}
return self;
}


The initialiseDatabase method is as follows

-(void)initialiseDatabase{

NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath
stringByAppendingPathComponent:@"ATDWCacheDatabase.sqlite"];

self.database = [FMDatabase databaseWithPath:path];

if(![self.database open]){
NSAssert2(0, @"0: Failed to open database. %d: %@",
[self.database lastErrorCode], [self.database lastErrorMessage]);
}

[self.database executeUpdate:@"CREATE TABLE config ( 'attribute'
VARCHAR(32) PRIMARY KEY, 'value' VARCHAR(64))"];
if ([self.database hadError]) {
NSAssert2(0, @"0: Error executing query. %d: %@", [self.database
lastErrorCode], [self.database lastErrorMessage]);
}

// Code that spawns off thread to sync data from website via
WebsiteController.
}

To get values from the config table I have a methods in the
DatabaseController class as follows

- (NSString *)getConfigValueFor:(NSString *)attribute {

NSString *value;

FMResultSet *rs = [self.database executeQuery:@"SELECT value FROM
config WHERE attribute = ?", attribute];
if ([rs next]) {
value = [rs stringForColumn:@"value"];
}
else {
value = nil;
}

return value;
}

In the WebSiteController class, it makes a call to the
DatabaseController to retrieve a value using

delta_date = [[DatabaseController sharedInstance]
getConfigValueFor:@"date_since_last_sync"];


All this seems to work fine. The DatabaseController init method only
ever gets called once, thus the initialiseDatabase method also only
ever gets called once.
The problem is though that when the WebsiteController calls the
getConfigValueFor method it gets to the

FMResultSet *rs = [self.database executeQuery:@"SELECT value FROM
config WHERE attribute = ?", attribute];

line and produces the following error

The FMDatabase <FMDatabase: 0x7e01e40> is not open.


I appologise now if this has more to do with my lack of understanding
of singletons rather than an FMDB issue, but does my method of
implementing with FMDB a singleton look correct?
Shouldn't the database connection still be open as I'm not actually
ever closing it?
or is ARC doing something in the background which is causing it to be
closed?

Appreciate any suggestion.

cheers,
Brett

Gus Mueller

unread,
Apr 3, 2012, 12:06:27 PM4/3/12
to fm...@googlegroups.com
On Apr 2, 2012, at 10:42 PM, Brett wrote:

> I appologise now if this has more to do with my lack of understanding
> of singletons rather than an FMDB issue, but does my method of
> implementing with FMDB a singleton look correct?
> Shouldn't the database connection still be open as I'm not actually
> ever closing it?
> or is ARC doing something in the background which is causing it to be
> closed?

I would suggest setting a breakpoint in FMDatabase's close method. Then if it is being closed somewhere, that'll help you track down where.

-gus

--

August 'Gus' Mueller
Flying Meat Inc.
http://flyingmeat.com/

Brett

unread,
Apr 3, 2012, 5:43:23 PM4/3/12
to fm...@googlegroups.com
Hi Gus,

Thanks for the reply.
I've set a breakpoint as you said and it never fires.
The app runs as mentioned previously and I get the same

The FMDatabase <FMDatabase: 0x7e01e40> is not open.

message when running the

FMResultSet *rs = [self.database executeQuery:@"SELECT value FROM
config WHERE attribute = ?", attribute];

line.

I've stepped through and can see the database connection being made.
The singleton returns the instance of the DatabaseController as
expected.
Is there any other way that the database connection would be closing?

It's really got me stumped.

cheers,
Brett

Gus Mueller

unread,
Apr 3, 2012, 5:50:30 PM4/3/12
to fm...@googlegroups.com

On Apr 3, 2012, at 2:43 PM, Brett wrote:

> I've set a breakpoint as you said and it never fires.
> The app runs as mentioned previously and I get the same
>
> The FMDatabase <FMDatabase: 0x7e01e40> is not open.
>
> message when running the
>
> FMResultSet *rs = [self.database executeQuery:@"SELECT value FROM
> config WHERE attribute = ?", attribute];
>
> line.
>
> I've stepped through and can see the database connection being made.
> The singleton returns the instance of the DatabaseController as
> expected.
> Is there any other way that the database connection would be closing?

I suppose there might be another way, but I can't think of any off the top of my head.

I'm not sure what to suggest at this point, other then really taking a hard look at your code and putting assertions all over the place, etc. If you do find the problem and it's FMDB's fault- make sure to let me know!

Brett

unread,
Apr 3, 2012, 6:29:23 PM4/3/12
to fm...@googlegroups.com
Thanks Gus, Appreciate the help.

I think I might have figured out whats happening. Your documentation
says "So don't instantiate a single FMDatabase object and use it
across multiple threads." which is pretty much exactly what I'm doing.
:(

I have the DatabaseController which creates the singleton (with an
instance of FMDatabase). I then spawn the WebController "sync" method
using

[NSThread detachNewThreadSelector:@selector(syncDataFromWebsite:)
toTarget:[WebController sharedInstance] withObject:nil];

When I am debugging

Brett

unread,
Apr 3, 2012, 6:30:17 PM4/3/12
to fm...@googlegroups.com
Sorry, please ignore the previous email.
Hadn't finished typing it and accidentally clicked send. :)
Reply all
Reply to author
Forward
0 new messages