Memory allocation keeps increasing while querying sqlite database - ios

+ (BOOL) isExistingTicket:(NSString *)TicketID{
int numrows=0;
sqlite3 *database;
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:dbName];
if(sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
NSString *sqlString = [NSString stringWithFormat:#"select count(*) from tickets WHERE ticket_id = '%#' LIMIT 1",TicketID];
sqlite3_stmt *selectStatement;
int returnValue = sqlite3_prepare_v2(database, [sqlString UTF8String], -1, &selectStatement, NULL);
if (returnValue == SQLITE_OK)
{
if(sqlite3_step(selectStatement) == SQLITE_ROW)
{
numrows= sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
}
else
sqlite3_close(database);
if (numrows > 0) {
return YES;
}else{
return NO;
}
}
Data set of around 200 comparing is using this query in my app. App memory usage keeps increasing when this function is called several times. It consumes more than 25Mb and does not decrease after that. Why is this happening? Can you suggest any optimizations?

This code closes the database only when the sqlite3_open call failed.
Move the sqlite3_close call into the first branch of the if.

Related

ios sqlite3 linking error

I'm starting to develop a small iOS application just for learning, and I'm attempting to use SQLite to store my app data. I'm using a simple CRUD operations, but when I compile the app (I want to try it in the device emulator) i've got this error
I've added libsqlite3.dylib to my project dependences.
I've tried many solutions, bun no one fix my problem.
Any idea about what i'm doing wrong?
Thank you so much
ps. The code are the following:
-(int) getPushCount {
int count = 0;
const char *dbpath = [databasePath UTF8String];
if(sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *query = [NSString stringWithFormat:#"SELECT COUNT(*) FROM recived_push WHERE read = 1"];
const char *getQuery = [query UTF8String];
if(sqlite3_prepare_v2(database, getQuery, -1, &statement, NULL) == SQLITE_OK) {
while(sqlite_step(statement) == SQLITE_ROW) {
count = sqlite_column_int(statement,0);
}
} else {
NSLog(#"Failed from sqlite3_prepare_v2.");
NSLog(#"Error is: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
sqlite3_close(database);
} else {
NSLog(#"Oops! Something went terribly wrong...");
NSLog(#"%s",sqlite3_errmsg(database));
return nil;
}
NSLog(#"**Count: %d",count);
return count;
}
change your code like this..
while (sqlite3_step(statement)== SQLITE_ROW) {
count = sqlite3_column_int(statement, 0);
}

iOS using SQLITE database. SQLITE_ROW returning 100 even with a limit set

Using SQLite Database Browser, I can send a query:
"SELECT latitude, longitude FROM locations WHERE businessid = 1453 LIMIT 3;"
and I get three rows of data. Well for some reason in my app's code the SQLITE_ROW value is 100 determined by assigning it to an int and logging. So this makes some sort of infinite loop and the app freezes indefinitely. I would really like to know why this code works for other areas of my app where I'm reading in other tables but not here. Here is the code.
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
for (int i = 0; i < appDelegate.userList.count; i++) // for each location in the user list, add to surrounding data
{
RMLocationItem *temp = [appDelegate.userList objectAtIndex:i];
NSString *sqlStatement1 = [[NSString alloc]init];
sqlStatement1 = [NSString stringWithFormat:#"SELECT latitude, longitude FROM locations WHERE businessid = %d limit 5;", temp.businessId];
const char *sqlStatement = [sqlStatement1 UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
//sqlite3_bind_int(compiledStatement, 1, temp.businessId);
//int sr = SQLITE_ROW;
//NSString* myNewString = [NSString stringWithFormat:#"%d", sr];
//NSLog(myNewString);
while( sqlite3_step(compiledStatement) == SQLITE_ROW)
{
double latitude = (double) sqlite3_column_double(compiledStatement, 0);
double longitude = (double) sqlite3_column_double(compiledStatement, 1);
sqlite3_reset(compiledStatement);
RMLocationItem *newLocation = [[RMLocationItem alloc]initWithName: temp.nameOfPlace distance:0 Id:temp.businessId longitude:longitude latitude:latitude address:NULL city:NULL];
[appDelegate.surroundingRestaurants addObject:newLocation];
}
}
else NSAssert1(0, #"Error while inserting data. '%s'", sqlite3_errmsg(database));
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
EDIT: Solved thank you, just like #rmaddy said, I took sqlite3_reset(compiledStatement); out and moved finalize up to just after the while loop.

Sqlite database cannot read column

I have a DBManager wich is fetching data from database (sqlite file). All other queries are fine, but this one seems to be somehow not working
-(NSArray *)readCountries{
NSLog(#"[DBManager] readCountries");
NSMutableArray *countriesArray = [[NSMutableArray alloc] init];
//open db from users filesystem
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char* sql = "SELECT DISTINCT country FROM aed ORDER BY rowid";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
//loop through results
while (sqlite3_step(statement) == SQLITE_ROW) {
//read data from record
NSString *_country;
char* tmpCountry = (char*)sqlite3_column_text(statement, 1);
NSLog(#"tmpCountry = %#", [NSString stringWithUTF8String:tmpCountry]);
if (tmpCountry != NULL) {
_country = [NSString stringWithUTF8String:tmpCountry];
}else{
_country = #"n/a";
}
NSLog(#"country = %#", _country);
[countriesArray addObject:_country];
}
}
//finalize statement
sqlite3_finalize(statement);
}
//close database
sqlite3_close(database);
NSLog(#"[DBManager] countriesArray has %d objects", [countriesArray count]);
return (NSArray*)countriesArray;
}
All I get from logs, that my array has 5 objects, which is fine - but it souldn't be only "n/a"... any idea? Other queries are good, they mostly use sqlite3_column_text so I don't get it, why it's not working here - maybe a fresh eye will help.
This is a confusing inconsistency with the sqlite C-api. When using the sqlite3_column_xxx functions, the column index is 0-based. But with the sqlite3_bind_xxx functions, the column index is 1-based.
Change this:
char* tmpCountry = (char*)sqlite3_column_text(statement, 1);
to:
char* tmpCountry = (char*)sqlite3_column_text(statement, 0);
BTW - you should add else statements to your sqlite3_open and sqlite3_prepare calls. If they fail you can log the error using the sqlite3_errmsg function.

SQLite3 library routine called out of sequence

the following code give me an library routine called out of sequence error, but I can't explain me where is the problem. Any ideas ?
- (BOOL)insertProduct:(Product *)product inOrder:(Order *)order withAmount:(int)amount
{
BOOL ok = NO;
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_database) == SQLITE_OK)
{
NSString * insertSQL;
int amount = [self getAmountForProduct:product inOrder:order];
NSLog(#"%i", amount);
if (amount != -1)
{
insertSQL = [NSString stringWithFormat: #"UPDATE ARTICOLIPERORDINE SET quantita = %i WHERE ordine = %i AND articolo = '%#'", amount, order.idOrdine, product.codice];
}
else
{
insertSQL = [NSString stringWithFormat: #"INSERT INTO ARTICOLIPERORDINE (ordine, articolo, quantita) VALUES(%i, '%#', %i)",order.idOrdine, product.codice, 1];
}
NSLog(#"%#", insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
if (sqlite3_prepare_v2(_database, insert_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_DONE)
{
ok = YES;
}
else
{
ok = NO;
NSLog(#"sqlite3 ERROR %s: %#",sqlite3_errmsg(_database), insertSQL);
}
sqlite3_finalize(statement);
sqlite3_close(_database);
}
else
{
NSLog(#"Error prepare = %s", sqlite3_errmsg(_database));
}
}
return ok;
}
The log print Error prepare = library routine called out of sequence
I have one approach.
Before this make sure that you have completed all your sql queries like connection open, close, finalize etc.
Before run your query actual into your code, execute that query into any database browser, You will see what is missing in your query.
As in my case I wrongly put the column name in query and run the code and I got the error multiple times. I review all the code carefully and execute the query into database browser and I found my mistake.

while(sqlite3_step(statement) == SQLITE_ROW) loops never execute

hi all
i have some problem in using sqlite in IOS. i have select data from database, and then i want to save that data in a variable. But when i use while(sqlite3_step(statement) == SQLITE_ROW) loop, the code never execute.
here is my code :
-(void)retrieveProjectNameFromDb:(NSString *)segmenId{
NSString *query;
NSString *nameProjectStr;
NSString *dbPath = [[NSBundle mainBundle] pathForResource:#"database" ofType:#"sqlite"];
if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(0, #"Database failed to open.");
}else {
query = [NSString stringWithFormat:#"SELECT remote_projectname, remote_base_uri FROM REMOTE_SETTING WHERE remote_settingid = '%#' ORDER BY remote_projectname", segmenId];
NSLog(#"query : %#", query);
}
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, nil)==SQLITE_OK){
NSLog(#"sqlite row : %d", SQLITE_ROW);
NSLog(#"sqlite 3 : %d", sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameProject = (char *)sqlite3_column_text(statement, 0);
if (nameProject == nil) {
NSLog(#"UNNAMED");
}else {
NSLog(#"else");
nameProjectStr = [NSString stringWithUTF8String:nameProject];
}
projectName.text = nameProjectStr;
nameProject = nil;
}
NSLog(#"project name : %#", projectName.text);
sqlite3_close(db);
}
}
when i nslog the value, sqlite3_step(statement) always show 101 and sqlite_row always show 100. Why it can happen??
can somebody help me, please?
thank you
Regards
-risma-
As you mentioned sqlite3_step(statement) always show 101 which means sqlite3_step has finished executions hence it means your sql query is not returning any rows from database. I would recommend you to first check in database if any record exists in table REMOTE_SETTING for remote_settingid which you are referring.
For your reference I took following constant snippet from sqlite.org
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
Remove the NSLog entry in which you are having sqlite3_step(). Since you have your NSLog statement executing sqlite3_step(), the record is already stepped through here. Hence, your while loop won't execute as there are no more rows to step through.
I think this will surely help you. :)
From your description of the logging output I would guess that your query is returning an empty row set. However I can see two other problems here:
You discard the result of your first call to sqlite3_step, because you log it then immediately call sqlite3_step again. That means you will miss the first row.
You probably should not be closing the database after a single query. You should finalize the statement after the query, but only close the database when your app shuts down.
Try:
if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, nil)==SQLITE_OK){
NSLog(#"sqlite row : %d", SQLITE_ROW);
int stepResult = sqlite3_step(statement);
NSLog(#"sqlite 3 : %d", stepResult);
while (stepResult == SQLITE_ROW) {
char *nameProject = (char *)sqlite3_column_text(statement, 0);
if (nameProject == nil) {
NSLog(#"UNNAMED");
}else {
NSLog(#"else");
nameProjectStr = [NSString stringWithUTF8String:nameProject];
}
projectName.text = nameProjectStr;
nameProject = nil;
stepResult = sqlite3_step(statement);
}
NSLog(#"project name : %#", projectName.text);
sqlite3_finalize(&statement);
}
Try with something like this..
sqlite3 *database1;
NSString *sqlStatement1 = #"";
if(sqlite3_open([databasePath UTF8String], &database1) == SQLITE_OK)
{
sqlStatement1 = [NSString stringWithString:#"SELECT uniqueid from shortlisted"];
sqlite3_stmt *compiledStatement1;
if(sqlite3_prepare_v2(database1, [sqlStatement1 cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement1, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement1) == SQLITE_ROW)
{
NSString * str = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
}
}
sqlite3_finalize(compiledStatement1);
sqlite3_close(database1);
}
Also close database instance whenever you open them.. if you are not closing an instance then that can cause issues..
Sorry I am pasting this from my project.. but actually I am in a bit hurry... I'll modify this answer when I reach home...

Resources