Loop through while(sqlite3_step(statement) until all the rows - ios

I am storing multiple values in Sqlite database in my iOS app.
I need to retrieve the values under "cellForRowAtIndexPath"
- (NSString *) retrieveDetailText :(NSString *) emailAddress :(NSString *) uidText :(NSString *) folderName {
NSString *detailText = nil;
const char *dbpath = [databasePath UTF8String];
//SQLIte Statement
NSString *selettablequery = [NSString stringWithFormat:#"select * from MailFolderDBTable"];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
if (sqlite3_prepare(database, [selettablequery UTF8String], -1, &statement, NULL) ==SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
char *uidfield = (char *) sqlite3_column_text(statement, 5);
NSString *uidStr = [[NSString alloc] initWithUTF8String: uidfield];
NSLog(#"retrieveDetailText: uidStr: %#", uidStr);
if([uidStr isEqualToString:uidText]) {
char *emailstring = (char *) sqlite3_column_text(statement, 6);
NSString *detailTextData = [[NSString alloc] initWithUTF8String: emailstring];
NSData *data = [[NSData alloc] initWithBase64EncodedString:detailTextData options:NSDataBase64DecodingIgnoreUnknownCharacters];
detailText = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
From this code, I need to loop through at while(sqlite3_step(statement) == SQLITE_ROW)
As I am calling retrieveDetailText under cellForRowAtIndexPath, and it is not looping through here while(sqlite3_step(statement) == SQLITE_ROW), It checks if([uidStr isEqualToString:uidText]) only one time.
How can i loop through while(sqlite3_step(statement) until all the rows checked and get the value.

If you only need one row which satisfies uidText, then you can change your query no?
//SQLIte Statement
NSString *selettablequery = [NSString stringWithFormat:#"select * from MailFolderDBTable where uid = %#", uidText];
Otherwise, you can fetch all the data before loading your tableView, in an array and then use it as your tableView data source.

Related

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

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.

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 Show Distinct Value From Sqllite Table in iOS?

i am Newbie in iOS Development, and First time Use Sqllite database so Sorry For this Question but i am So Confusing Please Give me Solution for this.
I added Data in to My Sqllite Table Like as
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_myDatabase) == SQLITE_OK) {
NSString *insertSQL = [NSString stringWithFormat:
#"INSERT INTO ALLREADTABLE (PostId, PostTitle, ImageLink, ShortDescription,Category,PostDate) VALUES (\"%#\", \"%#\", \"%#\", \"%#\",\"%#\",\"%#\")",
post_id, cell.headLabel.text, image,self.shortDiscription,cell.categoryLabel.text,cell.timeLabel.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_myDatabase, insert_stmt,
-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSString *string=[NSString stringWithFormat:#"Value Added %# %# %# %# %# %#",post_id, cell.headLabel.text, image,self.shortDiscription,cell.categoryLabel.text,cell.timeLabel.text];
NSLog(#"String %#",string);
} else
{
NSLog(#"Failed to add contact");
}
sqlite3_finalize(statement);
sqlite3_close(_myDatabase);
}
Then it is added data in to Data Base as I want and it also added Duplicate Value in to table , so For Distinct Value i Write a Code to Fetch data like as
- (void)getTextFomDB
{
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:
#"sampleDatabase.db"]];
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_myDatabase) == SQLITE_OK)
{
NSString *querySQL = #"SELECT DISTINCT PostId, PostTitle, ImageLink, ShortDescription,Category,PostDate FROM ALLREADTABLE";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_myDatabase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
[self.postId removeAllObjects];
[self.postTitle removeAllObjects];
[self.imageLink removeAllObjects];
[self.shortDecsription removeAllObjects];
[self.category removeAllObjects];
[self.postDate removeAllObjects];
while (sqlite3_step(statement) == SQLITE_ROW) {
//NSString *personID = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *postId = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 1)];
NSString *postTitle = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 2)];
NSString *ImageLink = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 3)];
NSString *shortDescrip = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 4)];
NSString *Category = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 5)];
NSString *postDate = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 6)];
[self.postId addObject:[NSString stringWithFormat:#"%# ", postId]];
[self.postTitle addObject:[NSString stringWithFormat:#"%# ",postTitle]];
[self.imageLink addObject:[NSString stringWithFormat:#"%#",ImageLink]];
[self.shortDecsription addObject:[NSString stringWithFormat:#" %#",shortDescrip]];
[self.category addObject:[NSString stringWithFormat:#" %#",Category]];
[self.postDate addObject:[NSString stringWithFormat:#" %#",postDate]];
}
sqlite3_finalize(statement);
}
sqlite3_close(_myDatabase);
}
}
Then it Give me Error like as
[NSPlaceholderString initWithUTF8String:]: NULL cString
Here I want Distinct Value From My SqlliteTable. please Give me Solution For that. I know It is easy But i am Newbie in Database so please Sorry
and Thanks in advance.
You are using initWithUTF8String to get values from database, So if there is a field in database which accept null data than it will gives you an error when you are trying to fetch null data from database.
I suggest you replace all data retrieving code like
NSString *postId = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 1)];
with below code:
NSString *postId = [NSString stringWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
This will replace not null data to an empty string.
This is being caused by trying to create a NSString object with a NULL string. It is on one of these lines:
[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, ...)];
So, before you create a NSString with the results of the sql statement you need to check for NULL like this:
char *tmp = sqlite3_column_text(statement, 1);
if (tmp == NULL)
postId = nil;
else
postId = [[NSString alloc] initWithUTF8String:tmp];
Reference: lnafziger

Tableview app delete from sqlite database

I have a tableview app where I am trying to delete data stored in a sqilte browser. When I delete the data in the simulator, the data does not reappear after closing and re-running the simulator. However, when I open the database where the original data was kept using sqlite browser, the deleted data still appears in the sqlite browser. Can someone advise on what I'm missing?
#import "DataAccess.h"
#import "sqlite3.h"
#import "Product.h"
#import "Company.h"
#implementation DataAccess
NSString *dbPathString;
sqlite3 *companyDB;
sqlite3 *productDB;
-(void) setCompanyListFromDB
{
NSLog(#"setCompanyListFromDB");
dbPathString = #"/Users/user/Desktop/telecom.db";
self.companyList = [self readCompanyDataFromDB];
NSLog(#"read all company data");
}
-(void) deleteCompany:(Company *)company andDeleteProduct:(NSIndexPath*)indexPath{
//pass the company from the tableview, then pass the row from the tablewview
Product *product = [company.products objectAtIndex:indexPath.row];
[self deleteProductFromDB:product.name];
[company.products removeObjectAtIndex:indexPath.row];
}
-(NSMutableArray*)readCompanyDataFromDB //returning companyList bc we want to use this for displaying in tableview
{
NSLog(#"readDataFromDB");
NSMutableArray *companyList = [[NSMutableArray alloc]init];
sqlite3_stmt *statement ;
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
// Reading Companies ....................................Start
NSLog(#"Reading Companies");
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM company"];
NSLog(#"Company SQL: %#", querySQL);
const char *query_sql = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_prepare(companyDB, query_sql, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"sqlite3_prepare");
while (sqlite3_step(statement)== SQLITE_ROW) //while stepping through database, if it returns a row it should keep going, cuts out if it returns something other than SQLITE_ROW
{
// 1|Apple|AAPL|593.1|apple.jpeg
NSString *companyID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSString *stockSymbol = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *stockPrice = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
NSString *logo = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 4)];
//Company *company = [Company initWithName:name logo:logo symbol:stockSymbol price:stockPrice];
Company *company = [[Company alloc]init];
company.companyID = companyID;
company.name = name;
company.logo = logo;
company.stockSymbol = stockSymbol;
company.stockPrice = stockPrice;
[company print];
[companyList addObject:company];
}
}
// Reading Companies ....................................Done
// Reading Products for each Company ....................................Start
sqlite3_close(companyDB);
}
for(Company *company in companyList){
NSMutableArray *productList = [self readProductDataFromDBForCompanyID:company.companyID ];
company.products = productList;
}
return companyList;
}
-(NSMutableArray*) readProductDataFromDBForCompanyID:(NSString*)companyId {
NSLog(#"readProductDataFromDB");
NSMutableArray *productList = [[NSMutableArray alloc]init];
sqlite3_stmt *statement ;
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
// Reading Products ....................................Start
NSLog(#"Reading Products");
NSString *querySQL = [NSString stringWithFormat:#"select * from product where productid = %#", companyId];
NSLog(#"Product SQL: %#", querySQL);
const char *query_sql = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_prepare(companyDB, query_sql, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"sqlite3_prepare");
while (sqlite3_step(statement)== SQLITE_ROW) //while stepping through database, if it returns a row it should keep going, cuts out if it returns something other than SQLITE_ROW
{
NSString *name = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
NSString *website = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 2)];
NSString *productID = [[NSString alloc]initWithUTF8String:(const char *)sqlite3_column_text(statement, 3)];
Product *product = [[Product alloc]init];
product.productID = productID;
product.name = name;
product.website = website;
[product print];
[productList addObject:product];
}
}
// Reading Products ....................................Done
sqlite3_close(companyDB);
}
// insert into product values('iPad','0','http://www.apple.com/ipad/',1);
return productList;
}
-(void) deleteProductFromDB:(NSString*)productname{
if (sqlite3_open([dbPathString UTF8String], &companyDB)==SQLITE_OK) { //when we do this process for products, we can skip opening companyDB bc it is already open - just do it once
NSLog(#"sqlite3_open");
NSString *querySQL = [NSString stringWithFormat:#"delete from product where productname = '%#'", productname];
NSLog(#"Product Delete SQL: %#", querySQL);
const char *deleteQuery = [querySQL UTF8String]; //converting to type of string C understands
if (sqlite3_exec(companyDB, deleteQuery, NULL, NULL, nil)==SQLITE_OK)
{
NSLog(#"Product Deleted");
}
sqlite3_close(companyDB);
}
}
#end
As it was mentioned in the comments - when your app will run in iOS it will be sandboxed. Moreover, if you will include sqlite database as a resource file with your application - it will get into /Resources folder inside your application folder. And everything in that folder is not writable.
So if you need a database that you want to read/write you need to put it under /Documents folder inside your application folder.

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.

Resources