Reputation: 1982
I am developing an app for ipad and i am using sqlite sentences (select, update, insert, delete).
I open (sqlite3_open) the database at the beginning and close (sqlite3_close) at the end of each sentence. But sometimes i´ve got the "database is locked" message.
I don´t know what can i do to solve this.
Thanks and sorry for this little information.
Upvotes: 4
Views: 13507
Reputation: 1
it is use for three methed 1.isert 2.update 3. delete.
-(NSMutableArray *)resultSet
-(void)insertWithTitle:(NSString *)title Body:(NSString *)body
-(BOOL)updateAtIndex:(int)index Title:(NSString *)title Body:(NSString *)body
NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:0] autorelease];
FMResultSet *rs = [db executeQuery:[self SQL:@"SELECT * FROM %@" inTable:TABLE_NAME]];
while ([rs next]) {
Record *tr = [[Record alloc] initWithIndex:[rs intForColumn:@"id"]
Title:[rs stringForColumn:@"title"]
Body:[rs stringForColumn:@"body"]];
[result addObject:tr];
[tr release];
}
[rs close];
2....
return result;
[db executeUpdate:[self SQL:@"INSERT INTO %@ (title, body) VALUES (?,?)" inTable:TABLE_NAME], title, body];
if ([db hadError]) {
NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
Delete record :
BOOL success = YES;
[db executeUpdate:[self SQL:@"DELETE FROM %@ WHERE id = ?" inTable:TABLE_NAME], [NSNumber numberWithInt:index]];
if ([db hadError]) {
NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
success = NO;
}
return success;
}
Upvotes: -1
Reputation: 7913
A good way to solve this is to wrap this into a C++ library. This way, you can can create the library wrapper on the stack. This means that the moment that the function goes out of scope, you can close the connection in the destructor.
(note that I use reference counting for the Objective-C)
For instance:
NSArray* ScoreBoard::getAllScores()
{
ScoreBoard::ensureExistingTable();
//Stack allocated
SqliteWrapper sqlite("Scores.sqlite");
NSArray* result = sqlite.RunQuery("SELECT * FROM Scores ORDER BY ID DESC");
return result;
//after this, the sqlite destructor is called
}
It is very nice that the Objective-C compiler allows you to merge C++. It can be extremely useful.
Also
void SqliteWrapper::Close()
{
sqlite3_close(db);
}
as Vincent has pointed out, you have to finalize the statement. If you want keep the connection open, use finalize after each statement. Close out the connection the moment you are discarding the connection.
This method works for me.
Upvotes: 0
Reputation: 4409
You probably opened the database before using the same simulator. To conclude all actions to a database and release all resources you always have to use both (!) statements:
sqlite3_finalize(statement);
sqlite3_close(database);
Upvotes: 3
Reputation: 4029
If I'm not mistaken , the problem with sqllite is that you can only access it once at a time. If you have multiple threads, you can run in this situation. Example:
Run method1 (which accesses the database) on thread t1. Run method2 (which accesses the database) on thread t2 after x seconds.
If method1 is not finished in those x seconds , both methods will access it at the same time. And , as I said , I know that sqllite does not support this.
You should try to flag the usage of your database and if you want to access it but it is in use , try again after x seconds. Like this:
- (void) generalMethodThatUsesDatabses
{
if(databaseIsUsed)
{
[self performSelector:@selector(generalMethodThatUsesDatabses) withObject:nil afterDelay:5];
return;
}
databaseIsUsed = TRUE; //global bool variable
//your code here
databaseIsUsed = FALSE;
}
Hope this helps. Cheers!
Upvotes: 7