BAD_ACCESS on SQLITE selection - iphone

I am getting EXC_BAD_ACCESS when I attempt to do anything with the value I'm selecting from the local SQLITE database on an iPhone development. The code for my function is
-(void) updateFromDB {
// Setup the database object
sqlite3 *database;
// Open DB
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *query = [NSString stringWithFormat:#"SELECT MOD_ID FROM MODULE;"];
//NSLog(#"QUERY: %#",query);
// Prepare statement
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
// Execute SQL
while (sqlite3_step(statement) == SQLITE_ROW) {
// Get MOD_IDs
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
//=======================
// Get Notice Module Data
//=======================
if (MOD_ID == 1) {
self.noticeModule = [[ModuleSetting alloc] initWithID:ID];
}
}
} else {
NSAssert1(0,#"Error: failed to prepare statement. '%s'", sqlite3_errmsg(database));
}
// Release the compiled statement from memory
sqlite3_finalize(statement);
} else {
sqlite3_close(database);
NSAssert1(0,#"Failed to open database. '%s'",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
The bad access occurs on the line
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
Thanks for any help you can offer!

%# denotes objects. But MOD_ID seems to be an integer. So your format should be %d,
NSString *ID = [NSString stringWithFormat:#"%d", MOD_ID];

You can't use %# in format strings for integers, only for Obj-C objects. For integers, use %d (or for NSInteger, I think it is recommended to use %ld).
Have a look at the String Format Specifiers guide.

MOD_ID is not a pointer, so %# isn't correct.

Use below
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%d",MOD_ID];

Related

Not able to update database

I am not able to update one field. Please Suggest me what is the wrong thing in my code.
Code:
- (int) updateTaskDoneDate:(double)donedate ontaskid:(int)taskId
{
sqlite3 *database;
#try {
if (sqlite3_open([self.databasePath UTF8String], &database) == SQLITE_OK)
{
NSString *sql_str = [NSString stringWithFormat:#"update task set donedate='%f' where taskid=%d ", donedate ,taskId];
NSLog(#"sql str: %#",sql_str);
const char *sql = [sql_str UTF8String];
sqlite3_stmt *statement;
statement = [self PrepareStatement:sql];
NSDate *myDate;
myDate=[NSDate date];
int a1 = sqlite3_bind_double(statement, 1, [myDate timeIntervalSince1970]);
int a2 = sqlite3_bind_int(statement, 2, taskId);
NSLog(#"a1a2 %d, %d", a1, a2);
if (statement)
{
if (a1 != SQLITE_OK || a2 != SQLITE_OK)
{
sqlite3_finalize(statement);
return 0;
}
sqlite3_step(statement);
}
sqlite3_finalize(statement);
}
}
#catch (NSException *exception){
[self showException:exception];
}
#finally {
sqlite3_close(database);
return 1;
}
}
A couple of observations:
You're using sqlite3_bind_xxx (which is good, much better than building the SQL with stringWithFormat), but you don't have any ? placeholders in your SQL. Your SQL should presumably be:
NSString *sql_str = #"update task set donedate=? where taskid=?";
You don't need the stringWithFormat call, because you're binding your variables. You also don't need the quotes around your double value, either.
You're not showing the prepare statement, but if it fails, are you logging sqlite3_errmsg?
Likewise on your bind statements, if they're not SQLITE_OK, you're not logging sqlite3_errmsg.
Your sqlite3_step isn't checking its return code at all, much less logging sqlite3_errmsg if it's not SQLITE_DONE.
Bottom line, you must bind with ? placeholders and you're flying blind because you're not logging sqlite3_errmsg on failures.

Update value in sqlite iphone sdk

I have a simple program that update a record of a table
The table is "person" with two columns "name" and "age";
some records have been inserted, as follows:
name age
tom 20
andy 30
han 25
Now I am writing a program to update a row in the table:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *text=#"andy";
NSString *query=[NSString stringWithFormat:#"UPDATE person SET age=%d WHERE name='%#'",30,text];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query UTF8String],-1,&statement,NULL);
sqlite3_finalize(statement);
sqlite3_close(contactDB);
The program works fine, but the database is not updated (I am using SQLite Manager to browser the database)
When I try reading from database, it works well:
NSString *database=[[NSBundle mainBundle] pathForResource:#"mytable" ofType:#"sqlite"];
sqlite3_open([database UTF8String],&contactDB);
NSString *query1=[NSString stringWithFormat:#"SELECT * FROM person WHERE age=%d;",30];
sqlite3_stmt *statement;
sqlite3_prepare_v2(contactDB,[query1 UTF8String],-1,&statement,NULL);
sqlite3_step(statement);
NSString *result=[[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 0)];
label.text=result;
sqlite3_finalize(statement);
sqlite3_close(contactDB);
-(void)updateSetting:(NSArray *)arr
{
if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
{
sqlite3_stmt *compiledStmt;
NSString *sqlStmt=[NSString stringWithFormat:#"UPDATE setting SET flow='%#',formate='%#' WHERE primaryKey=%i;",[arr objectAtIndex:0],[arr objectAtIndex:1],1];
if(sqlite3_prepare_v2(myDatabase, [sqlStmt UTF8String],-1,&compiledStmt, NULL)==SQLITE_OK)
{
NSLog(#"Successful update");
}
sqlite3_step(compiledStmt);
sqlite3_close(myDatabase);
}
}
I already faced this issues. Whats the problem behind this is you passed the query as a string format so you have to use the ; at the end of the query statement.
NSString *query=[NSString stringWithFormat:#"UPDATE questionbank SET age=%d WHERE name='%#';",30,text];
Please make a checking like below before you perform your sqlite3_step method.
const char *sqlQuery = "UPDATE SETTINGS SET someFlag = 0";
sqlite3_stmt *insertStatement = nil;
int success = 0;
if(sqlite3_prepare_v2(sqliteDatabase, sqlQuery, -1, &insertStatement, NULL) == SQLITE_OK)
{
success = sqlite3_step(insertStatement);
if(insertStatement)
{
sqlite3_finalize(insertStatement);
}
if(success == SQLITE_ERROR)
{
return NO;
}
return YES;
}
return NO;
So that you can figure out, where the problem is.
You need to check whether you could access and open the database or not. Simply place your update segment in a if-statement like this: if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK).
Also try to add NSLog(#"%s", sqlite3_errmsg(database)); after your prepare to see if there was any errors.
The answer for this problem is that the database in the main bundle is read-only
I can not insert data into sqlite3 file on XCode

iOS sqlite will return NULL when using SELECT statement

I'm very confused why the SELECT statement doesn't work correctly. It doesn't give me any errors, just returns null. I know it is writing the string correctly and the right string is there, it's just not reading it correctly. Everything as far as I know is correct because I use the same SQLstmt "method" for many other methods/functions similar to this. This one just doesn't make sense on why it shouldn't work.
- (NSString *)returnNote {
selStmt=nil;
NSLog(#"Reading note");
NSString *SQLstmt = [NSString stringWithFormat:#"SELECT 'Notes' FROM '%#' WHERE Exercises = '%#';", currentRoutine, currentExercise];
// Build select statements
const char *sql = [SQLstmt UTF8String];
if (sqlite3_prepare_v2(database, sql, -1, &selStmt, NULL) != SQLITE_OK) {
selStmt = nil;
}
// Building select statement failed
if (!selStmt) {
NSAssert1(0, #"Can't build SQL to read Exercises [%s]", sqlite3_errmsg(database));
}
NSString *note = [NSString stringWithFormat:#"%s", sqlite3_column_text(selStmt, 0)];
sqlite3_reset(selStmt); // reset (unbind) statement
return note;
}
You're not calling sqlite3_step. The statement is never executed.
NSString *querySQLS1 = [NSString stringWithFormat: #"SELECT Notes FROM \"%#\" where Exercises=\"%#\"", currentRoutine, currentExercise];
sqlite3_stmt *statements;
const char *query_stmts1 = [querySQLS1 UTF8String];
if(sqlite3_prepare_v2(UsersDB, query_stmts1, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"in prepare");
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"Query executed");
}
else {
NSLog(#"in else");
}
sqlite3_finalize(statement);
}

Getting error while executing SQLite command from application

I have this simple function in my application :
-(NSMutableArray *)SelectProductID:(NSMutableArray *)arr
{
NSLog(#"----------------");
sqlite3_stmt *statement;
NSMutableArray *arrPordID = [[NSMutableArray alloc]init];
#try
{
//Get productID
for(NSString *strSubProductID in arr)
{
NSString *s = [NSString stringWithFormat:#"SELECT ProductID FROM SubProducttable where SubProductID=%#",strSubProductID];
const char *sql = [s cStringUsingEncoding:NSASCIIStringEncoding];
if (sqlite3_prepare_v2(database, [s cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW){
char *dbString;
dbString = (char *)sqlite3_column_text(statement, 0);
NSString *pID = (dbString) ? [NSString stringWithUTF8String:dbString] : #"";
[arrPordID addObject:pID];
}
}
}
}
#catch (NSException *exception) {
#throw exception;
}
#finally {
sqlite3_finalize(statement);
}
return arrPordID;
}
I am encountering a strange problem here. When application reaches while (sqlite3_step(statement) == SQLITE_ROW){, loop is never entered. I don't know why. I executed the same query in SQLite manager (when application is not running). And I get result as a single one. The result I get is 2. But here I am getting nothing.
And yes, I always close the database in SQLite manager whenever I run my application. I have also cleaned the application, restarted XCode, and removed the application from simulator. But no success.
Also I saw a strange thing during debugging. While debugging, sqlite3_stmt *statement is always skipped. Is this the reason I am not getting any result?
Have you tried subproductId in single quotes?
NSString *s = [NSString stringWithFormat:#"SELECT ProductID FROM SubProducttable where SubProductID='%#'",strSubProductID];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
const char *sqlQuery = #"SELECT ProductID FROM SubProducttable where SubProductID=%#",strSubProductID;
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, statement, -1, &sqlQuery, NULL) == SQLITE_OK) {
while(sqlite3_step(sqlQuery ) == SQLITE_ROW) {
// Read the data and add to your array object
}
}
// Release the compiled statement from memory
sqlite3_finalize(statement);
}
sqlite3_close(database)

iOS SQLite Sum and retrieve data

I have a SQLite database that I am creating in my iOS application. A series of numbers are being stored in this database. I want to sum the entire column, and return the data to be displayed within the application.
Everything writing to the DB is working properly, but I am stuck trying to return the summed data. Any help would be greatly appreciated.
-(void) dataReturn: (NSString *) tableNamed{
NSString *myData = [NSString stringWithFormat:#"SELECT SUM(column1) AS data1 FROM myDB", tableNamed];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [myData UTF8String], -1, &statement, nil) ==SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW){
int *field2 = (int *) sqlite3_column_int(statement, 1);
NSString *myString =[[NSString alloc] initWithFormat:#"%#", field2];
}
}
}
Hello Nathan making a call as
[self dataReturn:#"Bill"];
to function
-(void)dataReturn:(NSString *)tableName{
sqlite3 *database;
sqlite3_stmt *statement;
NSString *queryString = [NSString stringWithFormat:#"SELECT SUM(price) AS TOTAL FROM %#", tableName];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
if(sqlite3_prepare_v2(database, [queryString UTF8String], -1, &statement, nil) == SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW) {
int field1 = sqlite3_column_int(statement, 0);
NSLog(#"The sum is %d ", field1);
}
}
}
}
will Fetch you desired data. The schema for Table "Bill" is "CREATE TABLE Bill (price double,quantity INTEGER)". The result fetched will have columns indexed from "0" so we pass 0 for first column. Hope you can take some hint from it. Cheers!!
int field1 = sqlite3_column_int(statement, 0);
From the sqlite3_column_int docs:
The leftmost column of the result set has the index 0.
Additionally, that function returns an int, not an int*. Try:
int field2 = sqlite3_column_int(statement, 0);