Insert dictionary in an SQLite db won't work - ios

I'm trying to updating the SQLite db on the iPhone with a dictionary returned by my server.
sqlite3_step return sqlite_ok but the database still remain empty.
Anyway inserted a log for a possible error after sqlite3_step and this return "database locked" so I think something is wrong with the sqlite function order in my code.
I've also verified that the dictionary contains data with a log inside the iteration and it gives me all I expect to find.
What's wrong here? Can someone help me?
Sorry for my bad english and thanks
Marco
//----- database update -----------------------------------------------------------------------------------------------------
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:#"DB.sqlite"];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
hasError= false;
const char *update_stmt="REPLACE INTO table VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)";
sqlite3_stmt *compiledstatement;
if(sqlite3_prepare_v2(database,update_stmt , -1, &compiledstatement, NULL)==SQLITE_OK) {
for (NSDictionary *item in [update objectForKey:#"table1"]) {
sqlite3_bind_int(compiledstatement, 1,[[item objectForKey:#"a"]integerValue]);
sqlite3_bind_text(compiledstatement,2,[[item objectForKey:#"b"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,3,[[item objectForKey:#"c"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,4,[[item objectForKey:#"d"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(compiledstatement,5,[[item objectForKey:#"e"] integerValue]);
sqlite3_bind_double(compiledstatement,6,[[item objectForKey:#"f"] doubleValue]);
sqlite3_bind_text(compiledstatement,7,[[item objectForKey:#"g"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,8,[[item objectForKey:#"s"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,9,[[item objectForKey:#"g"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,10,[[item objectForKey:#"u"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,11,[[item objectForKey:#"y"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(compiledstatement,12,[[item objectForKey:#"n"] integerValue]);
sqlite3_bind_int(compiledstatement,13,[[item objectForKey:#"k"] integerValue]);
//sqlite3_bind_text(compiledstatement,2,[#"" UTF8String], -1, SQLITE_TRANSIENT);
if(!sqlite3_step(compiledstatement)==SQLITE_DONE) {hasError= true; NSLog(#"error (%s)", sqlite3_errmsg(database));} //error
NSLog(#"error (%s)", sqlite3_errmsg(database));
sqlite3_reset(compiledstatement);
}
sqlite3_finalize(compiledstatement);
}else { NSLog(#"prepare FAILED (%s)", sqlite3_errmsg(database));}
} else {NSLog(#"opening error");}
sqlite3_close(database);
EDIT:
I'm not able to understand why this code won't work!!! I've not find the final solution.
I always get "library routine called out of sequence" at COMMIT, why?
Isn't this sequence correct?
-open
-begin
-prepare
-cycle the dictionary(bind, step and reset; for every item in dictionary I must insert or replace a row)
-finalize
-commit
-close
If I remove the begin and commit exec I have the error "database is locked" on "step", when the code try to insert the first row...
it's a nightmare...
Thank you again for your help!!
//----- database update -----------------------------------------------------------------------------------------------------
const char *updateTags_stmt="REPLACE INTO tags VALUES(?,?,?)";
if (sqlite3_open_v2([dbPath UTF8String], &database,SQLITE_OPEN_READWRITE,NULL) != SQLITE_OK) {
sqlite3_close(database);return;
}
if (sqlite3_exec(database, "BEGIN", 0, 0, 0)!=SQLITE_OK) {sqlite3_close(database);return;}
sqlite3_stmt *compiledstatement;
if(sqlite3_prepare_v2(database,updateTags_stmt , -1, &compiledstatement, NULL)!=SQLITE_OK) {sqlite3_close(database);return;}
for (NSDictionary *item in [update objectForKey:#"tags"]) {
sqlite3_bind_int(compiledstatement,1,[[item objectForKey:#"tid"] integerValue]);
sqlite3_bind_text(compiledstatement,2,[[item objectForKey:#"categoria"] UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledstatement,3,[[item objectForKey:#"tag"] UTF8String], -1, SQLITE_TRANSIENT);
if(sqlite3_step(compiledstatement)!=SQLITE_DONE) {
sqlite3_finalize(compiledstatement);
sqlite3_close(database);
return;
} else {if (sqlite3_reset(compiledstatement)!=SQLITE_OK){sqlite3_close(database);return;}}
}
if (sqlite3_finalize(compiledstatement)!=SQLITE_OK){sqlite3_close(database);return;}
if (sqlite3_exec(database, "COMMIT", NULL, NULL, 0)!=SQLITE_OK) {sqlite3_close(database);return;}
if (sqlite3_close(database)!=SQLITE_DONE){sqlite3_close(database);return;}

This code is wrong; it first inverts the return value of sqlite3_step, and then compares that value to SQLITE_DONE (which never succeeds because ! returns 0 or 1):
if(!sqlite3_step(compiledstatement)==SQLITE_DONE)
Do it correctly:
if (sqlite3_step(compiledstatement) != SQLITE_DONE)

Finally I've found the problem: there was another query on a different class in which then statement was not finalized so the DB still remains always open... two weeks for this lesson!! heheh sorry!

Related

when to call SQLite cleanup functions?

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.

sqlite3_step is returning error code 5 while inserting data into sqlite

I have an application using sqlite where I'm checking if a particular record exists in table. If not, I am inserting data into table but while inserting it is giving me error code 5.
This is my code
-(int)addPayOptions:(NSString*)owner:(NSString*)bank:(NSString*)number:(NSString*)scheme:(NSString*)type:(NSString*)expiryDate:(NSString*)name
{
NSString *queryString=nil;
NSString *dbPath = [DBManager getdbpath];
int val =0;
#try {
queryString=[NSString stringWithFormat:#"SELECT * FROM PAYTABLE WHERE NAME='%#'",name];
if (sqlite3_open([dbPath UTF8String], &database)==SQLITE_OK)
{
int resp_code =sqlite3_prepare_v2(database, [queryString UTF8String], -1, &statement, NULL);
NSLog(#"%d",resp_code);
if (sqlite3_prepare_v2(database, [queryString UTF8String], -1, &statement, NULL)==SQLITE_OK)
{
if (sqlite3_step(statement)==SQLITE_ROW)
{
val=0;
return val;
sqlite3_reset(statement);
}
else
{
BOOL checkinserted =[self insertPayOptions:owner :bank :number :0:scheme:type:expiryDate:name];
if (checkinserted)
{
val=1;
return val;
}
else
{
val=0;
return val;
}
}
sqlite3_finalize(statement);
}
}
sqlite3_close(database);
}
#catch (NSException *exception) {
}
return val;
}
-(BOOL)insertPayOptions:(NSString*)owner:(NSString*)bank:(NSString*)number:(NSString*)defaultOption:(NSString*)scheme:(NSString*)type:(NSString*)expiryDate:(NSString*)name
{
const char *dbpath = [dbPath UTF8String];
BOOL check = '\0';
if (sqlite3_open([dbPath UTF8String], &database)==SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:#"insert into PAYTABLE (OWNER,BANK,NUMBER,DEFAULT_OPTION,SCHEME,TYPE,EXPIRYDATE,NAME) VALUES('%#','%#','%#','%d','%#','%#','%#','%#')",owner,bank,number,0,scheme,type,expiryDate,name];
if(sqlite3_prepare_v2(database, [insertSQL UTF8String], -1, &statement, NULL)==SQLITE_OK)
{
NSLog(#"%d",sqlite3_step(statement));
if (sqlite3_step(statement)==SQLITE_DONE)
{
check=YES;
}
else
{
check =NO;
}
}
sqlite3_finalize(statement);
}
sqlite3_close(database);
return check;
}
A value of 5 is SQLITE_BUSY, which means that the database is currently busy doing something else (e.g., that a prior SQLite call was not properly finalized and closed).
Perhaps coincidentally, this method is a perfect example of precisely the sort of programming error that would cause this SQLITE_BUSY error. In your code, if the sqlite3_prepare_v2 statement succeeded, you will never get to your sqlite3_finalize or sqlite3_close statements because you return before getting to those finalize/close calls. Thus, the next time you call this method, it will tell you that the database is busy (because the prior call was never finalized and closed).
Be very, very wary of calling return inside your methods that perform SQLite calls, or if you do do employ return within the method, ensure that you call the appropriate sqlite3_finalize and sqlite3_close calls before returning. Or, better, refactor your code to minimize these return statements littered throughout the method, and it will be harder to make this mistake.
By the way, while this method conveniently illustrates the sort of programming error that would cause SQLITE_BUSY, it's not necessarily the case that this is the only situation in your code where you fail to finalize your statement or fail to close the database. You really should go through all of your SQLite related functions and consider each path of execution, and make sure that there's no possible way that sqlite3_finalize and sqlite3_close might fail to be called.
A couple of unrelated observations:
By the way, if a database call ever fails, it's often useful to log sqlite3_errmsg, which will be a little more informative regarding the precise nature of the error. For example, right now, if the prepare statement failed, you're silently returning, without any useful diagnostic information regarding any potential error.
You should avoid using try/catch blocks in Objective-C. While this is an important construct in other programming languages, in Objective-C you should do all of your error handling by looking at return codes (and where provided, examining NSError objects). In fact, since your catch block does nothing, you'll actually be obscuring any exceptions that take place, so it's even worse.
You should be very wary about using stringWithFormat to build your SQL statements. If the value included an apostrophe, your SQL would fail. Use sqlite3_bind_text instead, in conjunction with SQL that uses the ? placeholder.
The use of sqlite3_reset statement is unnecessary in this case. You only use sqlite3_reset when reusing a previously prepared sqlite3_stmt, which you are not doing here. You called sqlite3_reset after your return statement, so perhaps this is academic, but nonetheless, this sqlite3_reset call can be removed.
Hi following code works for me you can check,
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM PAYTABLE WHERE NAME='%#'",name]];
int rows;
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_step(statement);
rows = sqlite3_column_int(statement, 0);
sqlite3_finalize(statement);
sqlStatement = "insert into PAYTABLE (OWNER,BANK,NUMBER,DEFAULT_OPTION,SCHEME,TYPE,EXPIRYDATE,NAME) VALUES (?,?,?,?,?,?,?,?)";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(billDeskDB, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(compiledStatement, 1, [owner UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 2, [bank UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 3, [number UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 4, [#"0" UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 5, [scheme UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 6, [type UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 7, [expiryDate UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 8, [name UTF8String], -1, SQLITE_TRANSIENT);
}
}

SQLITE update table issue

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;

Can't insert rows into sqlite database using objective c

For some reason, the following code is not storing any data in my sqlite database. The return code is SQLITE_DONE (101) so it is not giving me any error messages. The method is being called a number of times to populate a few rows in the database. Can anyone see where i'm going wrong?
- (void)storePersonInDatabase:(Person *)person {
const char *sql = "INSERT INTO PERSON (ID, NAME, NOTES, ADDRESS, PROMOTED, VEGETARIAN) values (?, ?, ?, ?, ?, ?)";
sqlite3_stmt *statement;
// Prepare the data to bind.
NSData *imageData = person.imageData;
NSString *personId = [person.personId stringValue];
NSString *personName = person.name;
NSString *address = person.address;
NSString *notes = person.notes;
NSString *isVegetarian = (person.isVegetarian) ? #"1" : #"0";
NSString *isPromoted = (person.isPromoted) ? #"1" : #"0";
// Prepare the statement.
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
// Bind the parameters (note that these use a 1-based index, not 0).
sqlite3_bind_text(statement, 1, [personId UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [personName UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 3, [notes UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 4, [address UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 5, [isPromoted UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 6, [isVegetarian UTF8String], -1, SQLITE_TRANSIENT);
}
// Execute the statement.
int returnCode = sqlite3_step(statement);
if (returnCode != SQLITE_DONE) {
// error handling...
NSLog(#"An error occoured");
}
//This is how I set up the db
NSString *sqliteDb = [[NSBundle mainBundle] pathForResource:#"Persons" ofType:#"sqlite"];
if(sqlite3_open([sqliteDb UTF8String], &database) != SQLITE_OK){
NSLog(#"Unable to open database");
}
As a few people have suggested, you need to copy the database to a location outside of your project bundle. There you can read and write as you wish, otherwise you are essentially just creating new databases every time you try to run your 'storePersonInDatabase' method.
You should perform that same check that Daij-Djan provided before trying to interact with your database. You should also save the location or name of your database somewhere for easy access and file checking.
you show how you try to open a sqlite file in your app bundle
you cant write to your app bundle
the app bundle is read only
you need to copy it somewhere you can write to. It sounds like it should go to library/documents.
the pseudo code is:
if(!sqlite_already_in_library) {
[file_manager copyFileFrom:sqlite-in-bundle to:sqlite-in-library_path];
}

Insert into database issue

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.

Resources