Related
I am working with sqlite database in iOS.I have used CURD operation in my app.For example to insert data into the database i have used below code.
- (BOOL) saveData:(User *)user
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if([self getUserData:user.email] != nil)
{
[self updateUserData:user];
return YES;
}
else
{
NSString *insertSQL = [NSString stringWithFormat:
#"insert into users(userid,name,email,password,address,age,gender,phone,qualification,role,createddate,apiKey,priorityid,usertype) values (\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\")",user.userid,user.name,user.email,user.password,user.address,user.age,user.gender,user.phone,user.qualification,user.role,user.createddate,user.api_key,user.priority_id,user.user_type];
NSLog(#"%#",insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
sqlite3_finalize(statement);
// sqlite3_close(database);
return YES;
}
else
{
NSLog(#"%serrr is ",sqlite3_errmsg(database));
//sqlite3_reset(statement);
sqlite3_close(database);
return NO;
}
}
}
//sqlite3_reset(statement);
sqlite3_close(database);
return NO;
}
I am getting memory issues in my app due to sqlite database.I am not able to understand what should be order of calling sqlite3_reset();,sqlite3_finalize(), sqlite3_close().Please tell in reference to my code so that i can resolve all memory issues in my app
EDIT:
- (BOOL) insertSeMapData:(Client *)client : (NSString *)userid : (NSString *)sendemailto : (NSString *)assignworkordersto
{
BOOL result=NO;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
InspectionMapDetails *inspMap = [self getSEMapData:client :userid];
if(inspMap != nil)
{
[self updateSEMapData:client :userid :inspMap : sendemailto : assignworkordersto];
result=YES;
}
else
{
const char *insert_stmt = "insert into map(inspid,inspectorid,clientid,status,createddate,sendemailreportto,assignworkordersto) values (?,?,?,?, datetime(),?,?)";
if (sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL) == SQLITE_OK)
{
NSString *clientinspid=[NSString stringWithFormat:#"%#",client.inspid];
NSString *clientid=[NSString stringWithFormat:#"%#",client.clientid];
userid=[NSString stringWithFormat:#"%#",userid];
sqlite3_bind_text(statement, 1, [clientinspid UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [userid UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [clientid UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 4, [sendemailto UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 5, [assignworkordersto UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(statement) == SQLITE_DONE)
{
result = YES;
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"Unable to prepare statement: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
}
else
{
NSLog(#"Unable to open database: %s",sqlite3_errmsg(database));
}
return result;
}
Above function causing memory issue.Here Sqlite_open statement is causing a memory leak which i don't understand why?
There are simple guidelines, and to be blunt, your code doesn't follow any of them at all.
For each successful call to sqlite3_open you must call sqlite3_close.
For each successful call to sqlite3_prepare_v2 you must call sqlite3_finalize. Optionally, in between you may call sqlite3_reset zero or more times in cases where you reuse the prepared statement.
You should always check the result of calls to sqlite3_open and sqlite3_prepare_v2. If they fail, you should use sqlite3_errmsg to log what the problem was.
Do not build query strings using stringWithFormat. Instead, properly bind values to the query using appropriate calls to the various sqlite3_bind_xxx functions.
The code you posted violates all of these. You have plenty of cases where you don't close the database or finalize the prepared statement. And you are incorrectly building your query with stringWithFormat:.
Here's your code all fixed up. Note that I'm assuming all the values you are inserting are strings. Adjust accordingly for any non-string values.
- (BOOL) saveData:(User *)user
{
BOOL result = NO;
if([self getUserData:user.email] != nil)
{
[self updateUserData:user];
result = YES;
}
else
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
const char *insert_stmt = "insert into users(userid,name,email,password,address,age,gender,phone,qualification,role,createddate,apiKey,priorityid,usertype) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
if (sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, [user.userid UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [user.name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [user.email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [user.password UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [user.address UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, [user.age UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 7, [user.gender UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 8, [user.phone UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 9, [user.qualification UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 10, [user.role UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 11, [user.createddate UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 12, [user.api_key UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 13, [user.priority_id UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 14, [user.user_type UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(statement) == SQLITE_DONE)
{
result = YES;
}
sqlite3_finalize(statement);
}
else
{
NSLog(#"Unable to prepare statement: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
else
{
NSLog(#"Unable to open database: %s",sqlite3_errmsg(database));
}
}
return result;
}
Update based on the new edit:
Just like your original code, you violate a few of the rules. Your updated code doesn't quite follow the pattern I gave in my answer above.
The main issue now is that you open the database but you only close it under one of two possible code paths. If inspMap != nil you never close the database.
You really should refactor the code so you only open the database if inspMap is nil. I did something similar to your original code in my original answer.
I am trying to update a table in my sqlite database within an iOS app. I have used this update statement before, and it worked.
The below statement is returning a sqlite commit value of 0, BUT all the fields in the row to be updated are set to "< null >".
I don't get an error message ...
What is wrong with the statement?
-(void) UpdateSMUser :(NSString *) tableName
withField1:(NSString *) field1
field1Value:(NSString *) field1Value
andField2:(NSString *) field2
field2Value:(NSString *) field2Value
andField3:(NSString *) field3
field3Value:(NSString *) field3Value
andField4:(NSString *) field4
field4Value:(NSString *) field4Value
{
[self openDB];
sqlite3_stmt *updateStmt;
NSString *sql = [NSString stringWithFormat:#"UPDATE SMUser SET UserID = ?, Profile = ?, SMReg = ?, Date = ? WHERE UserID = '%#'" ,field1Value];
if (sqlite3_prepare_v2(db, [sql UTF8String] , -1,
&updateStmt, NULL) == SQLITE_OK)
{
sqlite3_bind_text(updateStmt, 1, [field1Value UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(updateStmt, 2, [field2Value UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(updateStmt, 3, [field3Value UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(updateStmt, 4, [field4Value UTF8String], -1, SQLITE_TRANSIENT);
}
// [self openDB];
char* errmsg;
NSLog(#"sqlite commit %d",sqlite3_exec(db, [sql UTF8String], NULL, NULL, &errmsg));
sqlite3_exec(db, [sql UTF8String], NULL, NULL, &errmsg);
if(SQLITE_DONE != sqlite3_step(updateStmt)){
NSLog(#"Error while updating. %s", sqlite3_errmsg(db));
}
else{
// [self clearClick:nil];
}
sqlite3_finalize(updateStmt);
sqlite3_close(db);
}
Thank you very much in advance ... it is driving me crazy!
sqlite3_exec() is an (obsolete) wrapper around sqlite3_prepare*()/sqlite3_step()/sqlite3_finalize().
You cannot use sqlite3_exec() with parameters.
You still have the correct sqlite3_step() call in your program; just remove both sqlite3_exec() calls.
i'm creating the tables as followed and i insert the data to that table and i retrieved the table values as well the image also it created,inserted and retrieved successfully,but not updating the image in the sqlite table below is my entire code help me thanks in advance
here is the create code
-(int) createTable:(NSString*) filePath
{
sqlite3* db = NULL;
int rc=0;
NSLog(#"create");
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"Failed to open db connection");
}
else
{
char * query ="CREATE TABLE IF NOT EXISTS places ( id INTEGER PRIMARY KEY AUTOINCREMENT,place TEXT ,locationname TEXT,time TEXT,description TEXT,notifyTime TEXT,radius TEXT,lat DOUBLE,lon DOUBLE ,notify TEXT,selection INTEGER,status INTEGER,radiusMeter DOUBLE,frequency INTEGER,notifiedStatus INTEGER,snoozeNooftimes INTEGER,snoozeStatus INTEGER,snoozeTime TEXT,reminderImage BLOB)";
char * errMsg;
rc = sqlite3_exec(db, query,NULL,NULL,&errMsg);
if(SQLITE_OK != rc)
{
NSLog(#"Failed to create table rc:%d, msg=%s",rc,errMsg);
}
else{
NSLog(#"Sucessfully Created ");
}
sqlite3_close(db);
}
return rc;
}
the table is successfully created by the above fields.And my insert code is below..
-(int) insert:(NSString *)filePath withName:(NSString *)place location:(NSString *)locationString description:(NSString*)description time:(NSString*)time notify:(NSString *)notifyTime radius:(NSString *)radius lat:(double)lat lon:(double)lon notify:(NSString *)notify selec:(int)selection stat:(int)status radius:(double)radiusMeter freq:(int)frequency notifyStatus:(int)notifiedStatus snoozeNooftime:(int)snoozeNoOfTimes snoozeStatus:(int)snoozeStat snoozeTime:(NSString *)snoozeTime img:(NSData *)imageData
{
sqlite3* db = NULL;
int rc=0;
sqlite3_stmt *stmt =NULL;
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE , NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"insert Failed to open db connection");
}
else
{
const char *insertSQL="INSERT INTO places (place,locationname,time,description,notifyTime,radius,lat,lon,notify,selection,status,radiusMeter,frequency,notifiedStatus,snoozeNooftimes,snoozeStatus,snoozeTime,reminderImage) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
if (sqlite3_prepare_v2(db, insertSQL, -1, & stmt, NULL) != SQLITE_OK)
{
NSLog(#"INSERT fails error: %s", sqlite3_errmsg(db));
}
else
{
sqlite3_bind_text(stmt, 1, [place UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [locationString UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [time UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [description UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [notifyTime UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, [radius UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(stmt, 7, lat);
sqlite3_bind_double(stmt, 8, lon);
sqlite3_bind_text(stmt, 9, [notify UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 10, selection );
sqlite3_bind_int(stmt, 11, status);
sqlite3_bind_double(stmt, 12, radiusMeter);
sqlite3_bind_int(stmt, 13, frequency);
sqlite3_bind_int(stmt, 14, notifiedStatus);
sqlite3_bind_int(stmt, 15, snoozeNoOfTimes);
sqlite3_bind_int(stmt, 16, snoozeStat);
sqlite3_bind_text(stmt, 17, [snoozeTime UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_blob(stmt, 18, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
int success = sqlite3_step(stmt);
sqlite3_reset(stmt);
if (success == SQLITE_ERROR)
{
}
else
{
// NSLog(#"insert query %#",query);
}
sqlite3_finalize(stmt);
sqlite3_close(db);
}
}
return rc;
}
And my update code is below:
-(void) update:(NSString *)filePath withName:(NSString *)place location:(NSString *)locationString description:(NSString*)description time:(NSString*)time notify:(NSString *)notifyTime radius:(NSString *)radius lat:(double)lat lon:(double)lon notify:(NSString *)notify selec:(int)selection where:(int)idd stat:(int)status radius:(double)radiusMeter freq:(int)frequency notifyStatus:(int)notifiedStatus snoozeNooftime:(int)snoozeNoOfTimes snoozeStatus:(int)snoozeStat snoozeTime:(NSString *)snoozeTime img:(NSData *)imageData
{
sqlite3* db = NULL;
int rc=0;
sqlite3_stmt* stmt =NULL;
rc = sqlite3_open_v2([filePath cStringUsingEncoding:NSUTF8StringEncoding], &db, SQLITE_OPEN_READWRITE , NULL);
if (SQLITE_OK != rc)
{
sqlite3_close(db);
NSLog(#"update all Failed to open db connection");
}
else
{
const char *sql = "UPDATE places SET place = ?, locationname = ?, time = ?, description = ?, notifyTime = ?, radius = ?, lat = ?, lon = ?, notify = ?, selection = ?, status = ?, radiusMeter = ?, frequency = ?, notifiedStatus = ?,snoozeNooftimes = ?,snoozeStatus = ?,snoozeTime = ? reminderImage = ? where id = ?";
if (sqlite3_prepare_v2(db, sql, -1, & stmt, NULL) != SQLITE_OK)
{
NSLog(#"update all fails error: %s", sqlite3_errmsg(db));
}
else
{
sqlite3_bind_text(stmt, 1, [place UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, [locationString UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, [time UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, [description UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, [notifyTime UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, [radius UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_double(stmt, 7, lat);
sqlite3_bind_double(stmt, 8, lon);
sqlite3_bind_text(stmt, 9, [notify UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 10, selection );
sqlite3_bind_int(stmt, 11, status);
sqlite3_bind_double(stmt, 12, radiusMeter);
sqlite3_bind_int(stmt, 13, frequency);
sqlite3_bind_int(stmt, 14, notifiedStatus);
sqlite3_bind_int(stmt, 15, snoozeNoOfTimes);
sqlite3_bind_int(stmt, 16, snoozeStat);
sqlite3_bind_text(stmt, 17, [snoozeTime UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_blob(stmt, 18, [imageData bytes], [imageData length], SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 0, idd);
int success = sqlite3_step(stmt);
sqlite3_reset(stmt);
if (success == SQLITE_ERROR)
{
}
else
{
NSLog(#"update all success");
}
sqlite3_finalize(stmt);
sqlite3_close(db);
}
}
}
When i update it getting the following error.
update all fails error: near "reminderImage": syntax error
UPDATE places SET place = ?, ... ,snoozeTime = ? reminderImage = ? where...
The comma between snoozeTime and reminderImage is missing.
I am new to Sqlite and I am working on an application which uses Sqlite.
I have succeeded in creation of table and inserting values into it.
I am trying to update the table but the table is not getting updated.
Below is the code for updating a table:
-(BOOL)updateData:(NSString *)screenName status:(NSString *)currentStatus{
const char *dbPath = [databasePath UTF8String];
if (sqlite3_open (dbPath, &database) == SQLITE_OK) {
NSString *updateSQL = [NSString stringWithFormat:#"Update productDetail Set status = \"%#\" where current_screen = \"%#\"",currentStatus,screenName];
// const char *update_stmt = "update productDetail Set status = ? Where screenName=?";
const char *update_stmt = [updateSQL UTF8String];
/*
if (sqlite3_prepare_v2(database, update_stmt, -1, &statement, NULL)) {
sqlite3_bind_text(statement, 0, [currentStatus UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [screenName UTF8String], -1, SQLITE_TRANSIENT);
}
*/
/*
char* errmsg;
sqlite3_exec(database, "COMMIT", NULL, NULL, &errmsg);
*/
sqlite3_prepare_v2(database, update_stmt, -1, &statement, NULL);
/*
sqlite3_bind_text(statement, 1, [currentStatus UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [screenName UTF8String], -1, SQLITE_TRANSIENT);
*/
if (sqlite3_step(statement) == SQLITE_OK) {
NSLog(#"Updated Successfully!!");
return YES;
}
else{
NSLog(#"error: %s",sqlite3_errmsg(database));
NSLog(#"Failed Updated");
}
int result=sqlite3_bind_text(statement, 1, Nil , -1, SQLITE_TRANSIENT);
NSLog(#"bind result= %i", result);
if(sqlite3_step(statement) != SQLITE_DONE) {
NSLog(#"Problems updating");
NSLog(#"error: %s",sqlite3_errmsg(database));
return NO;
}
else{
NSLog(#"Updated");
}
sqlite3_finalize(statement);
}
return YES;
}
Please let me know what I am doing wrong.
Thanks
ERROR:
Failed Updated
bind result= 21
Problems updating
rror: library routine called out of sequence
You have too much commented-out code, and the remaining code is garbled as a result.
Your code tries to bind a parameter, but your current query does not use parameters.
Furthermore, the return value of sqlite3_step can never be SQLITE_OK, and you are trying to execute the query twice (and the database complains because you did not call sqlite3_reset).
Use this code:
result = NO;
const char *update_stmt = "UPDATE productDetail SET status=? WHERE screenName=?";
if (sqlite3_prepare_v2(database, update_stmt, -1, &statement, NULL) != SQLITE_OK) {
NSLog(#"prepare error: %s", sqlite3_errmsg(database));
} else {
sqlite3_bind_text(statement, 1, [currentStatus UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [screenName UTF8String], -1, SQLITE_TRANSIENT);
if (sqlite3_step(statement) != SQLITE_DONE)
NSLog(#"execution error: %s", sqlite3_errmsg(database));
else
result = YES;
sqlite3_finalize(statement);
}
return result;
This thing is really weird for me i create an app, on my first view (login view) i enter email id and password and then verify this from database and if it ok then move to new view and in that view i fill some fields and then enter that data into database but it dnt enter data into my database .this verification of login view
-(NSInteger)verifyLoginEmail:(NSString *)email Password:(NSString *)password
{
NSInteger a=1;
const char *selectQuery="SELECT * FROM CreateProfile where email=? AND password=?";
sqlite3_stmt *statement;
if(sqlite3_open([destPath UTF8String],&studentDB)==SQLITE_OK)
{
//sqlite3_bind_int(statement, 1, sid);
if(sqlite3_prepare_v2(studentDB,selectQuery, -1, &statement, nil)==SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [password UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(statement)==SQLITE_ROW)
{
return a;
}
else
{
return 2;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(studentDB);
return 0;
}
and this code is for insert data from new view
-(void)insertName:(NSString *)name Email:(NSString *)email Password:(NSString *)password Pic:(NSString *)pic;
{
const char *insertQuery="insert into CreateProfile (name,email,pic,password) values (?,?,?,?)";
sqlite3_stmt *statement;
if(sqlite3_open([destPath UTF8String],&studentDB)==SQLITE_OK)
{
if(sqlite3_prepare_v2(studentDB, insertQuery, -1, &statement, nil)==SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [name UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [pic UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 4, [password UTF8String], -1, SQLITE_TRANSIENT);
//sqlite3_bind_int(statement, 2, rollno);
}
if(sqlite3_step(statement)==SQLITE_DONE){
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Profile Created" message:#"Your profile successfully added" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alert show];
[alert release];
}
sqlite3_finalize(statement);
}
sqlite3_close(studentDB);
}
when i directly go to view from changing view from main window i can enter fields into database but i cant enter into database when i login and then move to new view
In your (NSInteger)verifyLoginEmail:(NSString *)email Password:(NSString *)password funcation
You have written
sqlite3_bind_text(statement, 1, [email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [password UTF8String], -1, SQLITE_TRANSIENT);
replace those two lines with lines shown below
sqlite3_bind_text(statement, 0, [email UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 1, [password UTF8String], -1, SQLITE_TRANSIENT);
In Select Query the binding starts from 0 . and In insert statements the binding starts from 1.
and Instead of returning a , return some integer value like 1 , because your method's return type is NSInteger.
Hope it will work.