database locked error - iphone

iam getting database locked error .
-(IBAction)YesData:(id)sender
{
[self Check_Create_DB];
sqlite3 *database;
if(idimg == 0)
{
NSData *imgData = UIImagePNGRepresentation(image.image);
UIImage *dataImage=[[UIImage alloc] init];
dataImage=[UIImage imageWithData:imgData];
int ycount1=1;
int ncount1=0;
int neutcount1=0;
if(sqlite3_open([dbpath UTF8String],&database)==SQLITE_OK)
{
NSLog(#"Connection Open");
const char *sqlTmp="insert into
images(imgname,ycount,ncount,neutcount)values(?,?,?,?)";
sqlite3_stmt *cmp_sqlstmt;
int returnvalue=sqlite3_prepare_v2(database,sqlTmp,-1,&cmp_sqlstmt,NULL );
if(returnvalue == SQLITE_OK)
{
sqlite3_bind_blob(cmp_sqlstmt, 1, [imgData bytes], [imgData length], NULL);
sqlite3_bind_int(cmp_sqlstmt, 2, ycount1);
sqlite3_bind_int(cmp_sqlstmt, 3, ncount1);
sqlite3_bind_int(cmp_sqlstmt, 4, neutcount1);
if(SQLITE_DONE != sqlite3_step(cmp_sqlstmt))
NSAssert1(0, #"Error while inserting. '%s'",sqlite3_errmsg(database));
NSLog(#"insert successfully") ;
}
sqlite3_step(cmp_sqlstmt);
sqlite3_finalize(cmp_sqlstmt);
sqlite3_close(database);
lblvote.text=#"You Voted Yes";
[newView setHidden:NO];
}
else
{
sqlite3_close(database);
}
}
else
{
// [self Check_Create_DB];
//sqlite3 *database;
sqlite3_open([dbpath UTF8String],&database);
if(sqlite3_open([dbpath UTF8String],&database)==SQLITE_OK)
{
NSLog(#"Connection Open");
idycount+=1;
const char *sqlTmp="update Images set ycount=? where imgid= ?";
sqlite3_stmt *cmp_sqlstmt;
int returnvalue=sqlite3_prepare_v2(database,sqlTmp,-1,&cmp_sqlstmt,NULL);
NSLog(#"return value.....%d",returnvalue);
if(returnvalue == SQLITE_OK)
{
sqlite3_bind_int(cmp_sqlstmt,1,idycount );
sqlite3_bind_int(cmp_sqlstmt,2,idimg );
NSLog(#"updated");
if(SQLITE_DONE != sqlite3_step(cmp_sqlstmt))
NSAssert1(0, #"Error while updating. '%s'", sqlite3_errmsg(database));
sqlite3_reset(cmp_sqlstmt);
}
else
{
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_step(cmp_sqlstmt);
sqlite3_finalize(cmp_sqlstmt);
sqlite3_close(database);
}
else
{
sqlite3_close(database);
}
}
}

Seems to me that you havent closed the database properly (sqlite3_close(database)). This could have happened before your implementation looked like above where you close the db properly.Try to reinstall the the db and tables

Offtopic:
For future project take a look at FMDatabase.
FMDatabase is an Objective-C wrapper around SQLite

Related

Delete data sqllite on iphone - database is locked

my app crashed when I try to delete a data from my SqlLite db.
This is the error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error while deleting. 'database is locked'
This is all my code on database:
#import "Database.h"
static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
static sqlite3_stmt *addStmt = nil;
#implementation Database
#synthesize id_poi, pathDb, arrPoi;
- (id) initWithData:(NSDictionary *) data {
[super init];
NSLog(#"%#",[data objectForKey:#"pathDb"]);
NSLog(#"id_poi = %#",[data objectForKey:#"id_poi"]);
//setto l'id nello stato dell'oggetto
id_poi = [data objectForKey:#"id_poi"];
pathDb = [data objectForKey:#"pathDb"];
return self;
}
- (void) deletePoi {
if (sqlite3_open([pathDb UTF8String], &database) == SQLITE_OK) {
const char *sql = "delete from Poi where id_poi = ?";
sqlite3_stmt *deleteStmt;
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) == SQLITE_OK) {
//When binding parameters, index starts from 1 and not zero.
sqlite3_bind_int(deleteStmt, 1, [id_poi integerValue]);
if (SQLITE_DONE != sqlite3_step(deleteStmt)) {
NSAssert1(0, #"Error while deleting. '%s'", sqlite3_errmsg(database));
[[WPActivityIndicator sharedActivityIndicator] hide];
return;
}
} else {
NSAssert1(0, #"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_finalize(deleteStmt);
} else {
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
[[WPActivityIndicator sharedActivityIndicator] hide];
}
- (BOOL) checkIdPoi {
// lista temporanea
NSMutableArray *listaTemp = [[NSMutableArray alloc] init];
// Oggetto che contiene i vari elementi
NSMutableDictionary *dictionary;
NSMutableString *str_id_poi;//id della persona
if (sqlite3_open([pathDb UTF8String], &database) == SQLITE_OK) {
// query che ricava i valori
const char *sql = "select id_poi from Poi where id_poi = ?";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
sqlite3_bind_int(selectstmt, 1 , [id_poi integerValue]);
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
// ricaviamo i valori letti dalla query
str_id_poi = [NSMutableString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
// inseriamo tutti i valori letti in un unico oggetto
dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:str_id_poi, #"id_poi", nil];
//NSLog(#"str_id_poi = %#",str_id_poi);
[listaTemp addObject:dictionary];
[dictionary release];
return TRUE;
}
} else {
NSAssert1(0, #"Error while read data. '%s'", sqlite3_errmsg(database));
return FALSE;
}
}
else {
sqlite3_close(database);
return FALSE;
}
return FALSE;
}
- (void) addPoi {
//NSLog(#"%#",pathDb);
if (sqlite3_open([pathDb UTF8String], &database) == SQLITE_OK) {
const char *sql = "insert into Poi(id_poi) Values(?)";
sqlite3_stmt *addStmt;
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) == SQLITE_OK) {
NSString *str_id_poi = [[NSString alloc] initWithFormat:#"%d", [id_poi integerValue]];
sqlite3_bind_text(addStmt, 1, [str_id_poi UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(addStmt)) {
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
[[WPActivityIndicator sharedActivityIndicator] hide];
return;
} else {
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
//id_poi = sqlite3_last_insert_rowid(database);
}
//Reset the add statement.
sqlite3_reset(addStmt);
} else {
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_finalize(addStmt);
} else {
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
sqlite3_close(database);
[[WPActivityIndicator sharedActivityIndicator] hide];
}
// Carica i valori dal database passato come parametro
-(NSMutableArray*)getIdPOI {
// lista temporanea
NSMutableArray *listaTemp = [[NSMutableArray alloc] init];
// Oggetto che contiene i vari elementi
NSMutableDictionary *dictionary;
NSMutableString *str_id_poi;//id della persona
if (sqlite3_open([pathDb UTF8String], &database) == SQLITE_OK) {
// query che ricava i valori
const char *sql = "select id_poi from Poi";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
// ricaviamo i valori letti dalla query
str_id_poi = [NSMutableString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
// inseriamo tutti i valori letti in un unico oggetto
dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:str_id_poi, #"id_poi", nil];
//NSLog(#"str_id_poi = %#",str_id_poi);
[listaTemp addObject:dictionary];
[dictionary release];
}
//Reset the add statement.
sqlite3_reset(selectstmt);
} else {
NSAssert1(0, #"Error while read data. '%s'", sqlite3_errmsg(database));
}
//ADD THIS LINE TO YOUR CODE
sqlite3_finalize(selectstmt);
}
else
sqlite3_close(database);
sqlite3_close(database);
return listaTemp;
}
+ (void) finalizeStatements {
if(database) sqlite3_close(database);
if(deleteStmt) sqlite3_finalize(deleteStmt);
if(addStmt) sqlite3_finalize(addStmt);
}
-(void)dealloc {
[pathDb release];
[arrPoi release];
[super dealloc];
}
#end
Any suggest?
This type of error can occur when more then one query is fired for sqlite db. When you are executing any query, you need to synchronize all calls to the database.
Wrap all your database code in a #synchronized block like so:
#synchronized(self)
{
// database query code goes here
}
NB. this example assumes all database queries are executed from inside the 1 class. If not, you should replace 'self' with a common object instance that is shared by all classes that interface with the database. Alternatively, you can run all database statements on the main thread.
This usually happens when the database was opened and then not closed properly. It could be because you have the same instance of database opened from somewhere else.(Like a different class or SQLite manager).
It is usually advisable to create a singleton instance which communicates with your database rather opening and closing the database again and again.. hoping this helps.

Update table SQLIte in my iPhone App

I want to make it able in my app to insert data to sqlite database, and if the id for example is exist so to update this row.
i done the create with :
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
sqlite3_stmt *insertStmt = nil;
if(insertStmt == nil)
{
const char *insertSql = "INSERT INTO Category (id,name) VALUES(?,?)";
if(sqlite3_prepare_v2(database, insertSql, -1, &insertStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating insert statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(insertStmt, 1, 135);
sqlite3_bind_text(insertStmt, 2, [#"fds" UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(insertStmt))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
else
//NSLog("Inserted");
//Reset the add statement.
sqlite3_reset(insertStmt);
insertStmt = nil;
}
sqlite3_close(database);
Use the OR REPLACE qualifier:
INSERT OR REPLACE INTO Category ...
This relies on the existence of a UNIQUE constraint (usually the primary key) containing just the id column.
You can use following code for update:
-(void) Update:(NSString *)query {
sqlite3_stmt *statement=nil;
NSString *path = [self GetDatabasePath:DataBaseName] ;
if(sqlite3_open([path UTF8String],&databaseObj) == SQLITE_OK)
{
if(sqlite3_prepare_v2(databaseObj, [query UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_step(statement);
}
sqlite3_finalize(statement);
}
if(sqlite3_close(databaseObj) == SQLITE_OK){
}else{
NSAssert1(0, #"Error: failed to close database on memwarning with message '%s'.", sqlite3_errmsg(databaseObj));
}
}

Memory optimization for sqlite requests - help needed

I'm using two methods to r/w sqlite table:
+ (NSString *) getWeatherData:(int)rowID:(int)columnID {
NSString *savedWeatherData = [[NSString alloc] init];
if (sqlite3_open([[DBController getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "select * from TABLE where id=?";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
sqlite3_bind_int(selectstmt, 1, rowID);
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Weather *weatherObj = [[Weather alloc] initWithPrimaryKey:primaryKey];
weatherObj.weatherData = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, columnID)];
savedWeatherData = weatherObj.weatherData;
[weatherObj release];
}
}
}
return [savedWeatherData autorelease];
}
And to save some data:
+ (void) saveDataToDataBase:(NSString *)columnToUpdate:(int)rowID:(NSString *)value {
if (sqlite3_open([[DBController getDBPath] UTF8String], &database) == SQLITE_OK) {
updateStmt = nil;
NSString *sqlString = [[#"update TABLE set " stringByAppendingString:columnToUpdate] stringByAppendingString:#"=? where id=?"];
const char *sql = [sqlString UTF8String];
if(sqlite3_prepare_v2(database, sql, -1, &updateStmt, NULL) != SQLITE_OK) {
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(database));
} else { // select statement ok
sqlite3_bind_text(updateStmt, 1, [value UTF8String], -1, SQLITE_TRANSIENT); // replace first ? with value
sqlite3_bind_int(updateStmt, 2, rowID); // replace second ? with rowID
if(SQLITE_DONE != sqlite3_step(updateStmt)) {
NSAssert1(0, #"Error while updating. '%s'", sqlite3_errmsg(database));
} else {
// NSLog(#"Update completed !!!");
}
sqlite3_reset(updateStmt);
}
sqlite3_finalize(updateStmt);
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
With the Instruments, I see pretty big memory consumption for sqlite.
Info: during app startup, cca 100 different kind of data is stored in DB - for each data, this saveDataToDataBase method is called. (In case of no internet connection - getWeatherData would be used - and again cca 100 different kind of data would be read)
Please, can you instruct me - is it possible to optimize memory consumption.
Thanks a lot!
Kind regards!

Return inserted Id after sqlite3_finalize

Here is the code I am using to insert a record into the table... all I need is this function to capture and return back the inserted id of the record... is this possible? This code is working fine and returns YES for successful insert and NO for failures... but now im trying to return an integer insert id... but cant seem to figure out a way...
-(BOOL)insertEvent:(Event *)objEvent { Utils *objUtils = [[Utils alloc] init];
sqlite3_stmt *insertStmt = nil;
sqlite3 *aDatabase = nil;
int ret = sqlite3_enable_shared_cache(1);
if (sqlite3_open([databasePath UTF8String], &aDatabase) == SQLITE_OK)
{
if(insertStmt == nil)
{
NSString *aString = [NSString stringWithFormat:#"INSERT INTO tblEvent ('eventstartdate','eventdescription') VALUES ('%#','%#')",objEvent.eventstartdate, objEvent.eventdescription];
const char *sql = [aString UTF8String];
if(sqlite3_prepare_v2(aDatabase, sql, -1, &insertStmt, NULL) != SQLITE_OK)
{
NSAssert1(0, #"Error while creating insertTip add statement. '%s'", sqlite3_errmsg(aDatabase));
return NO;
}
[objUtils release];
}
if(SQLITE_DONE != sqlite3_step(insertStmt)) {
NSAssert1(0, #"Error while inserting into TipsTracker. '%s'", sqlite3_errmsg(aDatabase));
return NO;
}
sqlite3_reset(insertStmt);
if (insertStmt)
{
sqlite3_finalize(insertStmt);
insertStmt = nil;
}
}
sqlite3_close(aDatabase);
aDatabase = nil;
return YES;}
try this function sqlite3_last_insert_rowid(database);

inserting data in my sqlite database via iphone simulator

I am creating an iPhone application which makes use of sqlite database. I have one table in my database. Initially there are no rows in my table. I want that when I insert a new record via my iPhone simulator that record should be automatically updated to my database. How Could this be possible. Please anybody help me in solving this problem.
+ (void) getInitialDataToDisplay:(NSString *)dbPath
{
SQLAppDelegate *appDelegate = (SQLAppDelegate *)[[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sql = "select coffeeID, coffeeName from coffee";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Coffee *coffeeObj = [[Coffee alloc] initWithPrimaryKey:primaryKey];
coffeeObj.coffeeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
coffeeObj.isDirty = NO;
[appDelegate.coffeeArray addObject:coffeeObj];
[coffeeObj release];
}
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
+ (void) finalizeStatements
{
if (database) sqlite3_close(database);
if (deleteStmt) sqlite3_finalize(deleteStmt);
if (addStmt) sqlite3_finalize(addStmt);
if (detailStmt) sqlite3_finalize(detailStmt);
if (updateStmt) sqlite3_finalize(updateStmt);
}
- (id) initWithPrimaryKey:(NSInteger) pk
{
[super init];
coffeeID = pk;
coffeeImage = [[UIImage alloc] init];
isDetailViewHydrated = NO;
return self;
}
- (void) deleteCoffee
{
if(deleteStmt == nil) {
const char *sql = "delete from Coffee where coffeeID = ?";
if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
}
//When binding parameters, index starts from 1 and not zero.
sqlite3_bind_int(deleteStmt, 1, coffeeID);
if (SQLITE_DONE != sqlite3_step(deleteStmt))
NSAssert1(0, #"Error while deleting. '%s'", sqlite3_errmsg(database));
sqlite3_reset(deleteStmt);
}
- (void) addCoffee
{
if(addStmt == nil) {
const char *sql = "insert into Coffee(CoffeeName, Price) Values(?, ?)";
if(sqlite3_prepare_v2(database, sql, -1, &addStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating add statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(addStmt, 1, [coffeeName UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(addStmt, 2, [price doubleValue]);
if(SQLITE_DONE != sqlite3_step(addStmt))
NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
else
//SQLite provides a method to get the last primary key inserted by using sqlite3_last_insert_rowid
coffeeID = sqlite3_last_insert_rowid(database);
//Reset the add statement.
sqlite3_reset(addStmt);
}
- (void) hydrateDetailViewData
{
//If the detail view is hydrated then do not get it from the database.
if(isDetailViewHydrated) return;
if(detailStmt == nil) {
const char *sql = "Select price, CoffeeImage from Coffee Where CoffeeID = ?";
if(sqlite3_prepare_v2(database, sql, -1, &detailStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_int(detailStmt, 1, coffeeID);
if(SQLITE_DONE != sqlite3_step(detailStmt)) {
//Get the price in a temporary variable.
NSDecimalNumber *priceDN = [[NSDecimalNumber alloc] initWithDouble:sqlite3_column_double(detailStmt, 0)];
//Assign the price. The price value will be copied, since the property is declared with "copy" attribute.
self.price = priceDN;
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(detailStmt, 1) length:sqlite3_column_bytes(detailStmt, 1)];
if(data == nil)
NSLog(#"No image found.");
else
self.coffeeImage = [UIImage imageWithData:data];
//Release the temporary variable. Since we created it using alloc, we have own it.
[priceDN release];
}
else
NSAssert1(0, #"Error while getting the price of coffee. '%s'", sqlite3_errmsg(database));
//Reset the detail statement.
sqlite3_reset(detailStmt);
//Set isDetailViewHydrated as YES, so we do not get it again from the database.
isDetailViewHydrated = YES;
}
- (void) saveAllData
{
if(isDirty)
{
if(updateStmt == nil)
{
const char *sql = "update Coffee Set CoffeeName = ?, Price = ?, CoffeeImage = ? Where CoffeeID = ?";
if(sqlite3_prepare_v2(database, sql, -1, &updateStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating update statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(updateStmt, 1, [coffeeName UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(updateStmt, 2, [price doubleValue]);
NSData *imgData = UIImagePNGRepresentation(self.coffeeImage);
int returnValue = -1;
if(self.coffeeImage != nil)
returnValue = sqlite3_bind_blob(updateStmt, 3, [imgData bytes], [imgData length], NULL);
else
returnValue = sqlite3_bind_blob(updateStmt, 3, nil, -1, NULL);
sqlite3_bind_int(updateStmt, 4, coffeeID);
if(returnValue != SQLITE_OK)
NSLog(#"Not OK!!!");
if(SQLITE_DONE != sqlite3_step(updateStmt))
NSAssert1(0, #"Error while updating. '%s'", sqlite3_errmsg(database));
sqlite3_reset(updateStmt);
isDirty = NO;
}
//Reclaim all memory here.
[coffeeName release];
coffeeName = nil;
[price release];
price = nil;
isDetailViewHydrated = NO;
}
- (void)setCoffeeName:(NSString *)newValue
{
self.isDirty = YES;
[coffeeName release];
coffeeName = [newValue copy];
}
- (void)setPrice:(NSDecimalNumber *)newNumber
{
self.isDirty = YES;
[price release];
price = [newNumber copy];
}
- (void)setCoffeeImage:(UIImage *)theCoffeeImage
{
self.isDirty = YES;
[coffeeImage release];
coffeeImage = [theCoffeeImage retain];
}
Well, as I see you have this function +(void) finalizeStatements; where you close your DB and finalize your prepared queries.
First of all, you don't call this function from anywhere. Anyway if you are somehow calling this function, the code from is not correct, because you should first finalize all statements and only after that close the connection.
Read the documentation of sqlite3_close and sqlite3_finalize. What the documentation says about sqlite3_close:
Applications must [sqlite3_finalize | finalize] all [prepared statements] and [sqlite3_blob_close | close] all [BLOB handles] associated with the [sqlite3] object prior to attempting to close the object.
If that won't help you, try to finalize statements at the end of each method you prepare it.
Hope this helps you.
I'm not sure the database variable you've opened in getInitialDataToDisplay is still available when you try to addCoffee. Why don't you close that connection, and open a new one at the beginning of addCoffee (and close that when it completes)