"Database is locked" in delete operation in my sqlite - iphone

I have a function like this for delete table row in my apps, but I have an error that said "database is locked".
- (BOOL) deleteByCaption:(NSString *)registerCaption
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM tabelA WHERE CONTENT_CAPTION = \"%#\"", registerCaption];
const char *query_stmt = [querySQL UTF8String];
// NSMutableArray *resultArray = [[NSMutableArray alloc] init];
if(sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK){
if(sqlite3_step(statement) == SQLITE_ROW){
return YES;
}else{
NSLog(#"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
return NO;
}
}
sqlite3_reset(statement);
}
return NO;
}

You are missing sqlite3_finalize(). Look at //PUT HERE part in following code.
- (BOOL) deleteByCaption:(NSString *)registerCaption
{
BOOL isDeleted = NO; //EDIT
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM tabelA WHERE CONTENT_CAPTION = \"%#\"", registerCaption];
const char *query_stmt = [querySQL UTF8String];
// NSMutableArray *resultArray = [[NSMutableArray alloc] init];
if(sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK){
if(sqlite3_step(statement) == SQLITE_ROW){
isDeleted = YES;
//return YES; //EDIT
}else{
NSLog(#"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
//return NO; //EDIT
}
}
sqlite3_reset(statement);
sqlite3_finalize(statement); //PUT HERE
sqlite3_close(database); //EDIT
}
//return NO; //EDIT
return isDeleted; //EDIT
}
EDIT:
Try to set one variable to return.
Look at the edited portion in above code. Search for //EDIT.

In deleteByCaption function too, You are returning from function without closing data base.
You should write following statements before writing "RETURN YES" or "RETURN NO"
sqlite3_finalize(statement);
sqlite3_close(database);
Please check all functions where your have used sqlite3_open() function.
and make sure to write sqlite3_close() function before returning from that function.

Related

iOS Sqlite3 Delete Query Not Deleting Row

I am using this code to delete a row from the database for my ipad application,
-(BOOL) removeSegmentWithSegmentId:(NSInteger)sId
{
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
sqlite3_stmt *statement;
NSString *removeKeyword =[NSString stringWithFormat:#"DELETE FROM segment WHERE segment.segment_id = %d",sId];
const char *query = [removeKeyword UTF8String];
NSLog(#"%#",removeKeyword);
//if(sqlite3_prepare_v2(appDelegate->globalConnection,[removeKeyword UTF8String] , -1, &statement, NULL) == SQLITE_OK)
if(sqlite3_prepare_v2(appDelegate->globalConnection,query , -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE) {
sqlite3_finalize(statement);
return YES;
}
}
return NO;
}
but it is not working, can anyone guide me please?
Is your method returning YES?
A couple of things:
Always log sqlite3_errmsg on any failures
Right now, you're only doing sqlite3_finalize is sqlite3_step returns SQLITE_DONE, whereas you really should be doing it whenever you successfully did sqlite3_prepare_v2
So, I might suggest, at a minimum:
-(BOOL) removeSegmentWithSegmentId:(NSInteger)sId
{
BOOL success = NO;
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
sqlite3_stmt *statement;
NSString *removeKeyword = [NSString stringWithFormat:#"DELETE FROM segment WHERE segment.segment_id = %d",sId];
if (sqlite3_prepare_v2(appDelegate->globalConnection, [removeKeyword UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE)
{
success = YES;
}
else
{
NSLog(#"%s: step not ok: %s", __FUNCTION__, sqlite3_errmsg(appDelegate->globalConnection));
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"%s: prepare failure: %s", __FUNCTION__, sqlite3_errmsg(appDelegate->globalConnection));
}
return success;
}
Assuming this method was always returning YES, if you're not seeing records deleted, it must be that it's not finding a record to delete. (That is not considered a SQLite failure. The SQL was successfully executed, but the WHERE clause couldn't be satisfied.) You can verify this by defining the following method:
- (NSInteger)countSegmentWithSegmentId:(NSInteger)sId
{
NSInteger count = 0;
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
sqlite3_stmt *statement;
NSString *sql = [NSString stringWithFormat:#"SELECT segment_id FROM segment WHERE segment.segment_id = %d", sId];
if (sqlite3_prepare_v2(appDelegate->globalConnection, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
count++;
sqlite3_finalize(statement);
}
else
{
NSLog(#"%s: prepare failure: %s", __FUNCTION__, sqlite3_errmsg(appDelegate->globalConnection));
return -1;
}
return count;
}
And then put the diagnostic message in removeSegmentWithSegmentId:
- (BOOL)removeSegmentWithSegmentId:(NSInteger)sId
{
BOOL success = NO;
NSInteger count = [self countSegmentWithSegmentId:sId];
NSLog(#"%s there are %d records with segment_id of %d", __FUNCTION__, count, sId);
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
sqlite3_stmt *statement;
NSString *removeKeyword = [NSString stringWithFormat:#"DELETE FROM segment WHERE segment.segment_id = %d",sId];
if (sqlite3_prepare_v2(appDelegate->globalConnection, [removeKeyword UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
if(sqlite3_step(statement) == SQLITE_DONE)
{
success = YES;
}
else
{
NSLog(#"%s: step not ok: %s", __FUNCTION__, sqlite3_errmsg(appDelegate->globalConnection));
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"%s: prepare failure: %s", __FUNCTION__, sqlite3_errmsg(appDelegate->globalConnection));
}
return success;
}
if(sqlite3_step(statement) == SQLITE_DONE)
{
sqlite3_finalize(statement);
return YES;
}
else
{
NSLog(#"Failed to delete row %s", sqlite3_errmsg(database));
}
check the error msg.
Please try this
Steps are
1.Open database
2.Delete row from table
3.Close database
Also added NSLog to view the error in console
//------------------------------------------------------------------------
// Method : checkAndCreateDatabase
// Method to Check and Create the database
//------------------------------------------------------------------------
//Function to check & create a database
-(void) checkAndCreateDatabase
{
//-------------------------------------------
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager fileExistsAtPath:cDatabasePath];
//-------------------------------------------
//databse already there
if(success)
{
return;
}
//-------------------------------------------
//create database
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:cDatabaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:cDatabasePath error:nil];
}
//------------------------------------------------------------------------
// Method : checkAndCreateDatabase
// Method to open database
//------------------------------------------------------------------------
-(void) openDatabase
{
cDatabaseName = #"db.sqlite";
NSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [documentsPaths objectAtIndex:0];
cDatabasePath = [documentDir stringByAppendingPathComponent:cDatabaseName];
[self checkAndCreateDatabase];
//-------------------------------------------
if(sqlite3_open([cDatabasePath UTF8String],&database) == SQLITE_OK)
{
//nothing
}
}
//------------------------------------------------------------------------
// Method : closeDatabase
// Method to close database
//------------------------------------------------------------------------
- (void)closeDatabase
{
// Close the database.
if (sqlite3_close(database) != SQLITE_OK) {
//NSLog(#"Error: failed to close database with message '%s'.", sqlite3_errmsg(database));
}
}
-(BOOL) removeSegmentWithSegmentId:(NSInteger)sId
{
//for sharing variables of appdelegate file
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
BOOL isDeleted=NO;
[self openDatabase];
const char *sqlStatement;
sqlStatement = "DELETE FROM segment WHERE segment_id =?";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(appDelegate.database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
sqlite3_bind_int(compiledStatement, 1, sId);
if(SQLITE_DONE != sqlite3_step(compiledStatement))
{
NSLog( #"Error while deleting metadata of segment '%s'", sqlite3_errmsg(appDelegate.database));
}
else
{
NSLog(#"Deleted chart segment successfully !");
isDeleted=YES;
}
//-------------------------------------------
sqlite3_reset(compiledStatement);
}
else
{
NSLog( #"Error while deleting segment of chart '%s'", sqlite3_errmsg(appDelegate.database));
}
sqlite3_finalize(compiledStatement);
[self closeDatabase];
return isDeleted;
}
delete rows using name from text box.
(BOOL) deleteRow:(NSString *)name {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat: #"DELETE FROM person WHERE name='%#'",name];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_DONE) {
sqlite3_finalize(statement);
sqlite3_close(database);
return YES;
}
else
{
NSLog(#"%d",sqlite3_step(statement));
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return NO;
}
return Yes if deleted successfully and return NO if fail to delete.

How to delete all the contents from SQLite table in an iOS app

I want to delete all the rows from the table in my iPhone app. I am using following code but it is not deleting the data:
+(void)emptyData:(NSString*)dbPath{
NSString *query = #"delete from survey_question_responses";
const char *sqlStatement = [query UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSLog(#"result is here");
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
}
NSString *query1 = [NSString stringWithFormat:#"DELETE from TableName"];
[[DBManager sharedDatabase]executeQuery:query1];
where
-(void)executeQuery:(NSString*)_query
{
const char *sql = [_query cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *statement = nil;
if(sqlite3_prepare_v2(dataBaseConnection,sql, -1, &statement, NULL)!= SQLITE_OK)
{
NSAssert1(0,#"error preparing statement",sqlite3_errmsg(dataBaseConnection));
}
else
{
sqlite3_step(statement);
}
sqlite3_finalize(statement);
}
Get the path of the DB:
NSString*paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString*documentDirectory=[paths objectAtIndex:0];
NSSting*dBPath=[documentDirectory stringByAppendingPathComponent:#"dB.sql"];
Open the DB:
if(sqlite3_open([dBPath UTF8String], &database) == SQLITE_OK){
NSString*query=[NSString stringWithFormat:#"DELETE from tablename"];
}
Execute the query statement:
if(sqlite3_exec(database, [query UTF8String],NULL, NULL, NULL) == SQLITE_OK){
NSLog(#"Delete Query Success);
}
else{
NSLog(#"Delete Query Failed);}
sqlite3_close(database);
}
Hope this helps..

Cant able to Delete Row from sqlite Database

Can any one help me what he Problem in Code. I cant able to delete Row from the Database.
-(void) deleteData {
sqlite3_stmt *statement;
NSString *destinationPath = [self getDestinationPath];
const char *dbpath = [destinationPath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *updateSQL = [NSString stringWithFormat: #"DELETE FROM BirthdayListDB WHERE id=\"%#\"",details.ids];
const char *insert_stmt = [updateSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"Row deleted");
}
else
{
NSLog(#"Failed to delete row");
}
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
Here (sqlite3_stmt *statement;) i am not getting statement value. I am getting null value for statement.Can any 1 help me in solving this.
Thanks!
Just Replace
NSString *updateSQL = [NSString stringWithFormat: #"DELETE FROM BirthdayListDB WHERE id=\"%#\"",details.ids];
With
NSString *updateSQL = [NSString stringWithFormat: #"DELETE FROM BirthdayListDB WHERE id='%#'",details.ids];
Thanks,

not able to insert record in table in objective c

I made iPad application in which,
I want to insert record into database table, but I am unable to do the same.
here is my code snippet,
-(void) insertRecordIntoTableNamed: (NSString *) symbol{
NSString *sql = [NSString stringWithFormat:#"INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('%#',datetime())",symbol];
NSLog(#"sql=%#",sql);
char *err;
if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK)
{
sqlite3_close(db);
NSAssert(0, #"Error updating table.");
}
}
my NSLog shows:
sql=INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('PATNI',datetime())
this statement is correct, but i am unable to see VALUES PATNI and datetime() in my database table
here is rest of the code,
NSString *filePahs = Nil;
-(NSString *) filePath {
filePahs=[[NSBundle mainBundle] pathForResource:#"companymaster" ofType:#"sql"];
NSLog(#"path=%#",filePahs);
return filePahs;
}
result of above method is:
path=/Users/krunal/Library/Application Support/iPhone Simulator/5.0/Applications/9FF61238-2D1D-4CB7-8E24-9AC7CE9415BC/iStock kotak.app/companymaster.sql
-(void) openDB {
//---create database---
if (sqlite3_open([[self filePath] UTF8String], &db) != SQLITE_OK )
{
sqlite3_close(db);
NSAssert(0, #"Database failed to open.");
}
}
-(void) getAllRowsFromTableNamed: (NSString *) tableName {
//---retrieve rows---
NSString *qsql = #"SELECT * FROM recentquotes";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( db, [qsql UTF8String], -1, &statement, nil) ==
SQLITE_OK) {
NSLog(#"b4 while");
while (sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement, 0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
[recentqotarray addObject:field1Str];
[field1Str release];
}
//---deletes the compiled statement from memory---
sqlite3_finalize(statement);
NSLog(#"recentqotarray=%#",recentqotarray);
}
}
edit
i wrote this, and when i checked my log i got like this, "in find data" , i didn't got my sql=...
- (void) finddata
{
NSString *databasePath;
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
NSLog(#"in finddata");
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM recentquotes"];
NSLog(#"sql=%#",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"Inside recent quote table");
char *field1 = (char *) sqlite3_column_text(statement, 0);
NSLog(#"Column name=%s",field1);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
[recentqotarray addObject:field1Str];
NSLog(#"array=%#",recentqotarray);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
}
Thanks In Advance
In your:
NSString *sql = [NSString stringWithFormat:#"INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('%#',datetime())",symbol];
Instead of '%#' try using \"%#\" , and check if it inserts into your db.
EDIT:
I've been working on DB a lot lately, and i've been able to successfully insert data in my sqlite, i'll write down what i use check if it helps:
NSArray*dirPath;
NSString*docDir;
dirPath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docDir=[dirPath objectAtIndex:0];
databasePath=[docDir stringByAppendingPathComponent:#"example.sqlite"];
BOOL success;
NSFileManager*fm=[NSFileManager defaultManager];
success=[fm fileExistsAtPath:databasePath];
if(success)
{
NSLog(#"Already present");
}
NSString*bundlePath=[[NSBundle mainBundle] pathForResource:#"example" ofType:#"sqlite"];
NSError*error;
success=[fm copyItemAtPath:bundlePath toPath:databasePath error:&error];
if(success)
{
NSLog(#"Created successfully");
}
const char*dbPath=[databasePath UTF8String];
if(sqlite3_open(dbPath, &myDB)==SQLITE_OK)
{
NSString*insertSQL=[NSString stringWithFormat:#"insert into extable (name) values (\"%#\")",[nametextField.text]];
const char*insertStmt=[insertSQL UTF8String];
char *errmsg=nil;
if(sqlite3_exec(myDB, insertStmt, NULL, NULL, &errmsg)==SQLITE_OK)
{
NSLog(#"ADDED!");
}
sqlite3_close(myDB);
}

Exception while reading an empty table

Iam trying to read data from a table.
Initially it is empty. If i tried to read at that time it will cause an exception.
My code is given Below
-(NSMutableArray *) selectDataFrom:(NSString *) tableName
{
NSString *qsql = [NSString stringWithFormat:#"SELECT * FROM '%#' ",tableName];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( dataBase, [qsql UTF8String], -1, &statement, nil) == SQLITE_OK)
{
NSLog(#"INSIDE IF");
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"INSIDE WHILE");
// my code
}
}
return allData;
}
The first NSLog("INDISE IF"); is printed.
But the second one is not printing.
Mention some books to learn sqlite3 statements of iPhone [ eg: sqlite_prepare_v2();] not SQL
[ Sorry for my poor English]
THIS IS THE FULL CODE
-(NSMutableArray *) selectDataFrom:(NSString *) tableName
{
allData = [[NSMutableArray alloc] init];
NSString *qsql = [NSString stringWithFormat:#"SELECT * FROM '%#' ",tableName];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( dataBase, [qsql UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"REACHED 1");
myProgram = [[Programs alloc] init];
char *date = (char *) sqlite3_column_text(statement, 0);
myProgram.nss_Date = [[NSString alloc] initWithUTF8String:date];
char *type = (char *) sqlite3_column_text(statement, 3);
myProgram.nss_Type = [[NSString alloc]initWithUTF8String:type];
[nsma_allDonorsMA addObject:d_OneDonor];
}
}
else {
// NSLog(#"failed to select data");
}
return allData;
}
Try enabled breakpoints on exceptions and run your app in the debugger. It will show you exactly where you are calling objectAtIndex:. (It is not in the above code)
Where is your sqlite3_finalize() ??
You should release sqlite3_stmt structure in your sqlite3_prepare_v2 block, as following.
sqlite3_stmt *sql_stmt;
if (sqlite3_prepare_v2(...) == SQLITE_OK)
{
....
sqlite3_finalize(sql_stmt);
}