Not able to update database - iphone

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.

Related

not getting inside while loop when selecting a single row from sqlite

I have a problem with sqlite, when i select a single row from table and then check sqlite3_step(statement) == SQLITE_ROW both values are different and not getting inside while statement.
This is the code:
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"working777.............%d",sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"working888.............%d",SQLITE_ROW);
NSString *addressField = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSLog(#"............statement...........addressField %#, phoneField %#",addressField,phoneField);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
The proper way to create such a query would be like this:
NSString *querySQL = #"SELECT * FROM Major_Events WHERE temple_id = ?";
Then prepare the statement. I assume query_stmt is the char * value from querySQL.
Once the statement is prepared you then need to bind the value.
sqlite3_bind_int(statement, 1, temp_id); // bind is 1-based
Of course temp_id needs to be an int value and not a string. There are various sqlite3_bind_xxx statements for different data types. Use the appropriate one.
Once all of the query parameters are bound, you can execute the query using sqlite3_step.
The nice thing about this approach over string formats is that strings get properly escape and put in quotes for you. It's much harder to mess up and it makes your queries much safer against SQL injection attacks.
For many records:-
if (sqlite3_open([[self getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "select * from Place";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
}
else
{
sqlite3_close(database);
}
If you want a single record then change while to if
if(sqlite3_step(selectstmt) == SQLITE_ROW) {
rest everything will be same
I hope it helps and if your while loop is not getting executed then it means there is some problem with your query.You need to check that also.

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)

BAD_ACCESS on SQLITE selection

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];

XCode sqlite3 - SELECT always return SQLITE_DONE

a noob here asking for help after a day of head-banging....
I am working on an app with sqlite3 database with one database and two tables. I have now come to a step where I want to select from the table with an argument. The code is here:
-(NSMutableArray*) getGroupsPeopleWhoseGroupName:(NSString*)gn;{
NSMutableArray *groupedPeopleArray = [[NSMutableArray alloc] init];
const char *sql = "SELECT * FROM Contacts WHERE groupName='?'";
#try {
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docsDir = [paths objectAtIndex:0];
NSString *theDBPath = [docsDir stringByAppendingPathComponent:#"ContactBook.sqlite"];
if (!(sqlite3_open([theDBPath UTF8String], &database) == SQLITE_OK))
{ NSLog(#"An error opening database."); }
sqlite3_stmt *st;
NSLog(#"debug004 - sqlite3_stmt success.");
if (sqlite3_prepare_v2(database, sql, -1, &st, NULL) != SQLITE_OK)
{ NSLog(#"Error, failed to prepare statement."); }
//DB is ready for accessing, now start getting all the info.
while (sqlite3_step(st) == SQLITE_ROW)
{
MyContacts * aContact = [[MyContacts alloc] init];
//get contactID from DB.
aContact.contactID = sqlite3_column_int(st, 0);
if (sqlite3_column_text(st, 1) != NULL)
{ aContact.firstName = [NSString stringWithUTF8String:(char *) sqlite3_column_text(st, 1)]; }
else { aContact.firstName = #""; }
// here retrieve other columns data ....
//store these info retrieved into the newly created array.
[groupedPeopleArray addObject:aContact];
[aContact release];
}
if(sqlite3_finalize(st) != SQLITE_OK)
{ NSLog(#"Failed to finalize data statement."); }
if (sqlite3_close(database) != SQLITE_OK)
{ NSLog(#"Failed to close database."); }
}
#catch (NSException *e) {
NSLog(#"An exception occurred: %#", [e reason]);
return nil; }
return groupedPeopleArray;}
MyContacts is the class where I put up all the record variables.
My problem is sqlite3_step(st) always return SQLITE_DONE, so that it i can never get myContacts. (i verified this by checking the return value).
What am I doing wrong here?
Many thanks in advance!
I think you are not binding the value, if not use this
sqlite3_bind_text(stmt, 1, [groupName UTF8String], -1, SQLITE_STATIC);
You're not binding any value to your statement.
You're literally executing SELECT * FROM Contacts WHERE groupName='?' as is.
And that likely returns an empty set, which is why sqlite3_step returns SQLITE_DONE, there's nothing to read in the set, you're done.
This page has an example of binding parameters to a statement..
EDIT: Also, you don't need the quotes around ?
SELECT * FROM Contacts WHERE
groupName=?
then use sqlite3_bind_text