Getting database locked error while adding row 2nd time [duplicate] - ios

This question already has answers here:
sqlite error database is locked
(8 answers)
Closed 6 years ago.
I am getting error Database Locked.
at first attempt it adds the row but after that i am getting the error
database locked.
I am trying to make web page saver so at first time when app loads it is adding the row but when again I try to save any webpage it is not saving and I am getting the error database locked.
Even the deletion is also not happening after saving one web page.
#import "DBManager.h"
static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;
#implementation DBManager
+(DBManager*)getSharedInstance{
if (!sharedInstance) {
sharedInstance = [[super allocWithZone:NULL]init];
[sharedInstance createDB];
}
return sharedInstance;
}
-(BOOL)createDB{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent: #"browser.db"]];
BOOL isSuccess = YES;
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: databasePath ] == NO)
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
char *errMsg;
NSLog(#"insod");
const char *sql_stmt ="create table if not exists list(sno int primary key,name varchar(50),category varchar(30),path varchar(500),fav int)";
if (sqlite3_exec(database, sql_stmt, NULL, NULL, &errMsg)
!= SQLITE_OK)
{
isSuccess = NO;
NSLog(#"Failed to create table");
}
sqlite3_close(database);
return isSuccess;
}
else {
isSuccess = NO;
NSLog(#"Failed to open/create database");
}
}else{
NSLog(#"File Exist");
}
return isSuccess;
}
-(BOOL) Delete:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"delete from list where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
NSLog(#"error: %s",sqlite3_errmsg(database));
sqlite3_finalize(statement);
return NO;
}
}else{
sqlite3_close(database);
return NO;
}
}
-(NSDictionary *) CatList:(NSString *) cat{
const char *dbpath = [databasePath UTF8String];
NSDictionary *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL =[NSString stringWithFormat:#"select name,path from list where category like '%#'",cat];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
// NSLog(#"inside list");
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
NSMutableArray *arr2 = [[NSMutableArray alloc] init];
// NSMutableArray *arr3 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
//NSLog(#"%#",name);
NSString *category = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
[arr2 addObject:category];
// //NSLog(#"%#",dept);
// NSString *path = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)];
// [arr3 addObject:path];
}
sqlite3_finalize(statement);
dict = #{#"name":arr1,#"path":arr2};
//NSLog(#"%#",dict);
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
- (BOOL) saveData:(NSString*)name category:(NSString*)category path:(NSString*)path{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *highest = #"select max(sno) from list";
const char *Query = [highest UTF8String];
if (sqlite3_prepare_v2(database, Query, -1, &statement, NULL) == SQLITE_OK){
if (sqlite3_step(statement) == SQLITE_ROW){
int sno = sqlite3_column_int(statement, 0);
NSString *insertSQL = [NSString stringWithFormat:#"insert into list values(\"%d\",\"%#\",\"%#\", \"%#\",\"%d\")",sno+1,name, category, path,0];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
NSString *insertSQL = [NSString stringWithFormat:#"insert into list values(\"%d\",\"%#\",\"%#\", \"%#\",\"%d\")",1,name, category, path,0];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(database, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}
}
sqlite3_close(database);
}
return NO;
}
-(BOOL) Fav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"update list set fav = 1 where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
return NO;
}
}
-(NSArray *) GetListFav{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"select name from list where fav = 1";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
}
sqlite3_finalize(statement);
dict = arr1;
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
-(BOOL) removeFav:(NSString *) name{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK){
NSString *query = [NSString stringWithFormat:#"update list set fav = 0 where name like '%#'",name];
const char *stmt = [query UTF8String];
sqlite3_prepare_v2(database, stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE){
sqlite3_finalize(statement);
return YES;
}else {
sqlite3_finalize(statement);
return NO;
}
}else{
return NO;
}
}
-(NSArray *) GetList{
const char *dbpath = [databasePath UTF8String];
NSArray *dict;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = #"select name from list";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"inside list");
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[arr1 addObject:name];
}
sqlite3_finalize(statement);
dict = arr1;
}else{
NSLog(#"error: %s",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
return dict;
}
#end

You can only access sqllite once at a time. If you have multiple threads, you can run in this situation. Example:
So always try to close database once it is used using:
sqlite3_close(database);

You need to make sure every sqlite3_open is balanced with a sqlite3_close before trying to do sqlite3_open again:
Your saveData method has quite a few return statements that will prevent the database from ever calling sqlite3_close. Make sure all paths out of the method close the database properly. In the end, this means that you'll try to open the database although it's already open.
Or, better, just open the database once and leave it open, eliminating the repeated opening and closing of the database.
Your Delete, Fav, and removeFav methods are also not closing the database.
A few unrelated observations:
You should be wary about using stringWithFormat to build SQL with string parameters. If the string being searched for had a apostrophe in it, your code will fail. Use ? placeholders and then use sqlite3_bind_text to bind values to those placeholders.
If you make your sno column a AUTOINCREMENT, you won't have to do that "get the max sno before inserting new row" logic. Thus, the CREATE statement might look like:
create table if not exists list (
sno integer primary key autoincrement,
name text,
category text,
path text,
fav integer)
You can then omit sno from the INSERT statements, and it will automatically be assigned a unique identifier.

Related

Memory Issue in sqlite database iOS? [duplicate]

This question already has an answer here:
when to call SQLite cleanup functions?
(1 answer)
Closed 6 years ago.
I have used sqlite database in my app.I am doing CURD operation.I get data from json then i convert that data into arrays after that from arrays i insert the data into sqlite database.In my app when data can be upto more than 1000 records.When database is done then i get memory warning.
I have one function for Inserting data.It firstly check if data exists then update data else insert new record
[[DBManager getSharedInstance]insertData:object];
Function definition -
(BOOL) insertData:(SubComponent *)subcomponent
{
const char *dbpath = [databasePath UTF8String];
if([self getSubComponentDataBySubclientClientInspectionid:subcomponent.componentid : subcomponent.componentsubclientid:subcomponent.componentClientid : subcomponent.componentinspectionid] != nil)
{
[self updateCompSubComponentDataBySubclientId:subcomponent];
return YES;
}
else
{
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if (sqlite3_exec(database, [#"PRAGMA CACHE_SIZE=500000;" UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
NSLog(#"Successfully changed cache size");
}
else
NSLog(#"Error: failed to set cache size with message %s.", sqlite3_errmsg(database));
NSLog(#"inside isnert query");
NSString *insertSQL = [NSString stringWithFormat:
#"insert into subcomponent(subcomponentid,name,createddate,subclientid,clientid,cliententityid, inspectionid, initialstatus,componentclientname,componentsubclientname, checkedstatus) values (\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%#\",\"%ld\",\"%#\",\"%#\",\"2\")",subcomponent.componentid,subcomponent.componentName,subcomponent.componentcreateddate,subcomponent.componentsubclientid,subcomponent.componentClientid, subcomponent.componentEntityid,subcomponent.componentinspectionid,(long)subcomponent.componentStatus,subcomponent.componentClientName,subcomponent.componentSubclientName];
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);
return YES;
}
else
{
NSLog(#"REMASH DB ERROR %s",sqlite3_errmsg(database));
// sqlite3_reset(statement);
//sqlite3_close(database);
sqlite3_finalize(statement);
return NO;
}
}
sqlite3_close(database);
}
return YES;
}
GET DATA FUNCTION
- (SubComponent*) getSubComponentDataBySubclientClientInspectionid:(NSString*)componentid : (NSString *)subclientid : (NSString *)clientId : (NSString *)inspectionid
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"select * from subcomponent where subcomponentid = \"%#\" and subclientid = \"%#\" and clientid = \"%#\" and inspectionid = \"%#\"",componentid,subclientid, clientId,inspectionid];
NSLog(#"gghgh query is %#",querySQL);
const char *query_stmt = [querySQL UTF8String];
SubComponent *resultArray = [[SubComponent alloc]init];
if (sqlite3_prepare_v2(database,query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *component_id = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
resultArray.componentid = component_id;
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 1)];
resultArray.componentName = name;
NSString *createddate = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 2)];
resultArray.componentcreateddate = createddate;
NSString *subclientid = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 3)];
resultArray.componentsubclientid = subclientid;
NSString *clientid = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 4)];
resultArray.componentClientid = clientid;
NSString *entityid = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 5)];
resultArray.componentEntityid = entityid;
NSString *inspectionid = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 6)];
resultArray.componentinspectionid = inspectionid;
NSString *clientName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 8)];
resultArray.componentClientName = clientName;
NSString *subclientName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 9)];
resultArray.componentSubclientName = subclientName;
// sqlite3_finalize(statement);
// sqlite3_close(database);
return resultArray;
}
else
{
// sqlite3_finalize(statement);
// sqlite3_close(database);
return nil;
}
}
else
{
NSLog(#"error is %s",sqlite3_errmsg(database));
}
}
// sqlite3_reset(statement);
// sqlite3_finalize(statement);
sqlite3_close(database);
return nil;
}
Update Function
-(void)updateCompSubComponentDataBySubclientId:(SubComponent *)subcomponent
{
NSLog(#"inside update data");
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if (sqlite3_exec(database, [#"PRAGMA CACHE_SIZE=500000;" UTF8String], NULL, NULL, NULL) == SQLITE_OK) {
NSLog(#"Successfully changed cache size");
}
else
NSLog(#"Error: failed to set cache size with message %s.", sqlite3_errmsg(database));
NSString *querySql=[NSString stringWithFormat:
#"UPDATE subcomponent SET name=\"%#\", createddate=\"%#\", cliententityid =\"%#\",componentclientname=\"%#\", componentsubclientname = \"%#\", checkedstatus = \"2\" where subcomponentid = \"%#\" and subclientid = \"%#\" and clientid = \"%#\" and inspectionid =\"%#\"",subcomponent.componentName,subcomponent.componentcreateddate, subcomponent.componentEntityid,subcomponent.componentClientName,subcomponent.componentSubclientName,subcomponent.componentid, subcomponent.componentsubclientid,subcomponent.componentClientid,subcomponent.componentinspectionid];
const char *sql=[querySql UTF8String];
if(sqlite3_prepare_v2(database,sql, -1, &statement, NULL) == SQLITE_OK)
{
if(SQLITE_DONE != sqlite3_step(statement))
{
NSLog(#"REMASH Error while updating. '%s'", sqlite3_errmsg(database));
}
else
{
//sqlite3_reset(statement);
NSLog(#"Update done successfully!");
}
}
NSLog(#"NOT OK");
sqlite3_finalize(statement);
sqlite3_close(database);
}
}
PS:Can somebody suggest whether use of sqlite_finilaize(),sqlite_close().sqlite_reset() is correct by seeing my code.Because memory is increasing.
This is not a Database issue.
This issue is caused because Application doesn't have a storyboard for the device you are trying to run upon.
XCode no valid compiled storyboard at path

How to prevent duplicate data in SQLite3 in iOS 7?

I am trying to prevent duplicate values in SQlite DB.These are essentially a list of names along with which I am storing date as NSString as well.Now what I want to do is , insert a name only once and if inserted second time I want to update the date for it?So far I am able to insert new record, however not able to update it.What am I missing?
-(NSString *)viewDataBaseForCity:(NSString *)cityName addedDate:(NSString *)dateAdded{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT cityname FROM CITIES WHERE cityname=%#", cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL)== SQLITE_OK)
{
//This part is not executed at all
if (sqlite3_step(statement)==SQLITE_ROW)
{
self.tempcityName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSLog(#"Found city name : -%#",self.tempcityName);
return self.tempcityName;
}else{
NSLog(#"Not Found");
return nil;
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
}
return nil;
}
-(void)checkforupdate:(NSString *)cityName addedDate:(NSString *)dateAdded{
{
if(tempcityName == cityName)
{
NSString *querySQL = [NSString stringWithFormat:#"UPDATE CITIES set id=%# WHERE cityname=%#", dateAdded, cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"updated successfully");
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
else
{
[self insertintotable:cityName addedDate:dateAdded];
}
}
}
-(void)insertintotable:(NSString *)cityName addedDate:(NSString *)dateAdded{
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *insert_sql = [NSString stringWithFormat:#"INSERT INTO CITIES(cityname,id)VALUES (\"%#\",\"%#\")",cityName,dateAdded];
const char *insert_stmt = [insert_sql UTF8String];
sqlite3_prepare_v2(citiesDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement)==SQLITE_DONE)
{
NSLog(#"Saved");
}
else{
NSLog(#"NOT Saved");
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
}
}
Now the fields of table are created as below.
- (void)initDatabase{
//Putting in caches
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains
(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
databasePath = [cacheDir
stringByAppendingPathComponent:#"CityList.db"];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:databasePath]==NO) {
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK) {
char *errMsg;
NSString *sql_stmt = #"CREATE TABLE IF NOT EXISTS CITIES (";
sql_stmt = [sql_stmt stringByAppendingString:#"cityname TEXT PRIMARY KEY UNIQUE, "];
sql_stmt = [sql_stmt stringByAppendingString:#"id TEXT)"];
if (sqlite3_exec(citiesDB, [sql_stmt UTF8String], NULL, NULL, &errMsg)!=SQLITE_OK) {
NSLog(#"Failed to create table");
}
else
{
NSLog(#"CITIES table created successfully");
}
sqlite3_close(citiesDB);
}else {
NSLog(#"Failed to open/create database");
}
}
}
The below code will help you to do what you want. First check for the cityname you are entering if it exists in database table then update if not exists just insert into the database table.
#synthesis tempcityName;
-(BOOL)saveCity:(NSString *)cityName addedDate:(NSString *)dateAdded{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT cityname FROM CITIES WHERE cityname=%#", cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(citiesDB, query_stmt, -1, &statement, NULL)== SQLITE_OK)
{
if (sqlite3_step(statement)==SQLITE_ROW)
{
tempcityName = [[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
}
else{
[self.insertintotable:cityName];
}
sqlite3_finalize(statement);
}
sqlite3_close(citiesDB);
[self.checkforupdate:cityName];
}
To check the data is eligible to update or not:
-(void)checkforupdate:(NSString *)cityName
{
if(tempcityName == cityName)
{
NSString *querySQL = [NSString stringWithFormat:#"UPDATE CITIES set id=%# WHERE cityname=%#", dateAdded, cityName];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_beaconDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"updated successfully");
}
sqlite3_finalize(query_stmt);
sqlite3_close(citiesDB);
}
else
{
[self.insertintotable:cityName];
}
}
If the data is not eligible to update then call to insert in DB table
-(void)insertintotable:(NSString *)cityName
{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &citiesDB)==SQLITE_OK) {
//This inserts same name multiple times.
NSString *insert_sql = [NSString stringWithFormat:#"INSERT INTO CITIES(cityname,id)VALUES (\"%#\",\"%#\")",cityName,dateAdded];
const char *insert_stmt = [insert_sql UTF8String];
sqlite3_prepare_v2(citiesDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement)==SQLITE_DONE)
{
NSLog(#"Saved");
return YES;
}
else{
NSLog(#"NOT Saved");
return NO;
}
sqlite3_finalize(statement);
sqlite3_close(citiesDB);
}
First try to update the date.
If this fails (i.e., if sqlite3_changes says no rows were modified), insert a new row:
execute("UPDATE Cities SET id = ? where cityname = ?", ...);
if (sqlite3_changes(citiesDB) == 0) {
execute("INSERT INTO Cities(cityname, id) VALUES(?,?)", ...);
}
First of all you retrieve all data of name from table using Retrieve Query.
if ([RetriveDat containsObject:#"New Data"])
{
// Update Quert
}
else
{
// Insert Query
}

Sqlite always returns only 1 row

The count returns 3 ,as i have 3 rows in the column. But when i try to publish the name , it only returns 1 row.
please take a look at my code.
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
#"SELECT MESSAGE from CHATCOMPLETE"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_chatDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
NSLog(#"Name is %#",name);
}
}
else{
NSLog(#"Not found");
// return nil;
}
sqlite3_reset(statement);
}
}
Change your if/else to a while to step through all the rows:
while (sqlite3_step(statement) == SQLITE_ROW) {
NSString *name = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
NSLog(#"Name is %#",name);
}
Then you can process all of the results.
And you should change sqlite3_reset to sqlite3_finalize. And don't forget to close the database too.

Error no such table in iphone sqlite select query?

I am having tabbed iPhone application.In the first tab I created sqlite table and inserted values to the table,these are done successfully.In the second tab I am able to get the values from table but in third class when I am executing the select query, I am getting the no such table exception.
Even I deleted the app from simulator and cleaned the project,but I got the same problem.
Kindly give me solutions.
Coding for create and insert:
-(void)InsertLoginDetails:(NSString *)user fun:(NSString *)pwd{
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO Login ( USERNAME, PASSWORD) VALUES (\"%#\", \"%#\")",
user, pwd];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"Inserted");
} else {
NSLog(#"Failed to insert");
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
}
-(void)createLoginTable{
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc]
initWithString: [docsDir stringByAppendingPathComponent:
#"login.db"]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath ] == NO)
{
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS Login (ID INTEGER PRIMARY KEY AUTOINCREMENT, USERNAME TEXT, PASSWORD TEXT)";
if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
NSLog(#"Failed to create table");
}
sqlite3_close(_contactDB);
NSLog(#"Table created");
} else {
NSLog(#"Failed to open/create database");
}
}
}
Code for getting values:
-(void)checkLoginSession{
///////////////GET DB DATAS///////////////////////
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK)
{
NSString *querySQL = #"SELECT USERNAME, PASSWORD FROM Login";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_contactDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
strDBUsername = [[NSString alloc]
initWithUTF8String:
(const char *) sqlite3_column_text(
statement, 0)];
strDBPwd = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 1)];
NSLog(#"Settings page Login Details %# %#", strDBUsername , strDBPwd );
// _address.text = addressField;
//
// _phone.text = phoneField;
// _status.text = #"Match found";
} else {
// _status.text = #"Match not found";
// _address.text = #"";
// _phone.text = #"";
}
sqlite3_finalize(statement);
}
else{
NSLog(#"SQLITE NOT OK");
NSLog(#"Error %s ", sqlite3_errmsg(_contactDB));
}
sqlite3_close(_contactDB);
}

SQLite, insert data into a DB from different Views

We have declared the following code in the default ViewController.m:
-(void)saveData{
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%#\", \"%#\", \"%#\")",
name.text, address.text, phone.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
name.text = #"";
address.text = #"";
phone.text = #"";
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
}
-(void)findContact{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT address, phone FROM contacts WHERE name=\"%#\"", name.text];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *addressField = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
address.text = addressField;
NSString *phoneField = [[NSString alloc]
initWithUTF8String:(const char *)
sqlite3_column_text(statement, 1)];
phone.text = phoneField;
status.text = #"Match found";
} else {
status.text = #"Match not found";
address.text = #"";
phone.text = #"";
}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
}
}
-(void)viewDidLoad{
[super viewDidLoad];
NSString *docsDir;
NSArray *dirPaths;
dirPaths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir=[dirPaths objectAtIndex:0];
databasePath=[[NSString alloc]initWithString:[docsDir stringByAppendingPathComponent:#"contacts.db"]];
NSFileManager *filemgr=[NSFileManager defaultManager];
if([filemgr fileExistsAtPath:databasePath]==NO)
{
const char *dbpath=[databasePath UTF8String];
if(sqlite3_open(dbpath, &contactDB)==SQLITE_OK)
{
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";
if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
status.text = #"Failed to create table";
}
sqlite3_close(contactDB);
} else {
status.text = #"Failed to open/create database";
}
}
}
It works, but we want to access to that database (contactDB) from different viewControllerName.m ; we have tried the following:
// Scene2ViewController.m
-(void)incrementoBarra {
if (barra.progress == 1) {
//In this method we want to insert the address data into the specified name.
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO CONTACTS (name, address) VALUES (\"%#\", \"%d\")",
usuario, tiempo];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(contactDB, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
sqlite3_finalize(statement);
sqlite3_close(contactDB);
}
}
//
[self performSelector:#selector(hideImage) withObject: nil afterDelay:1.0];
}
}
It didnĀ“t work due to errors with the variables and the database as these were not well declared
How do we have to implement those variables and database to work with them from different .m?
Thank you for your time!
I think to this question there are allot of answers, so i'll just explain the one i would be going for, and try to explain why. Here goes!
Since you've got similar logic that you want to use in different locations (in this case multiple files), i would move this logic to a new class (.h and .m file for implementation). Considering it's logic that interacts with the database i would go ahead and name it "DatabaseManager". This class should now give you access to the logic you'd need.
To make sure you're always able to acces DatabaseManager, it might be smart to make it a Singleton (see http://en.m.wikipedia.org/wiki/Singleton_pattern).

Resources