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.
Related
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);
}
I have a "messages table" , and i want only to retrieve the "user ID" with his last message.
I tried to add "2 sql statements" inside each other , But it keeps on looping without stopping,
sqlite3_stmt *statement;
NSMutableArray * messages = [[NSMutableArray alloc]init];
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:
#"SELECT DISTINCT FROMID , USERNAME from CHATCOMPLETE"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(_chatDB,
query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
int userID = [[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)] integerValue];
NSString *querySQL2 = [NSString stringWithFormat:
#"SELECT MESSAGE , USERNAME from CHATCOMPLETE where FROMID=\"%d\"",userID];
const char *query_stmt2 = [querySQL2 UTF8String];
if (sqlite3_prepare_v2(_chatDB,
query_stmt2, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"LAST MESSAGE %#",[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)]);
sqlite3_reset(statement);
}
}
}
sqlite3_reset(statement);
}
}
return messages;
UPDATE:
This is the insert message
-(void)saveData:(NSString *)message toID:(int)toID fromID:(int)fromID isRead:(BOOL)read date:(NSDate *)date messageID:(int)messageID userName:(NSString*)userName
{
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: #"INSERT INTO CHATCOMPLETE (MESSAGE, TOID, FROMID, READ, date, MESSAGEID, USERNAME) VALUES (\"%#\", \"%d\", \"%d\", \"%c\", \"%#\", \"%d\", \"%#\")", message, toID, fromID, read, date,messageID,userName];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_chatDB, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
NSLog(#"DONE");
/* status.text = #"Contact added";
name.text = #"";
address.text = #"";
phone.text = #"";*/
} else {
// status.text = #"Failed to add contact";
}
sqlite3_finalize(statement);
sqlite3_close(_chatDB);
}
}
This is the query to get the last message with a given fromID:
SELECT * FROM chatting WHERE fromID=9999 ORDER BY id DESC LIMIT 1
In SQLite 3.7.11 or later, the following query will return the message with the largest date for each sender:
SELECT *, MAX(date)
FROM ChatComplete
GROUP BY FromID
There are a few issues:
You have only one sqlite3_stmt variable for your two nested queries. You want a separate sqlite3_stmt for each.
You are calling sqlite3_reset. That is only used when binding new values to ? placeholders in your prepared statement, which is not applicable here. Worse, you're calling it inside your loop.
Unrelated to the problem at hand, but for each prepared statement, don't forget to call sqlite3_finalize when done looping through the results, in order to release the memory used when preparing the statements.
Thus, you might want something like:
sqlite3_stmt *userStatement;
sqlite3_stmt *messageStatement;
int rc; // the return code
NSMutableArray * messages = [[NSMutableArray alloc]init];
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_chatDB) == SQLITE_OK)
{
const char *query_stmt = "SELECT DISTINCT FROMID , USERNAME from CHATCOMPLETE";
if (sqlite3_prepare_v2(_chatDB, query_stmt, -1, &userStatement, NULL) != SQLITE_OK)
{
NSLog(#"%s: prepare userStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
else
{
while ((rc = sqlite3_step(userStatement)) == SQLITE_ROW)
{
int userID = [[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)] integerValue];
const char *query_stmt2 = "SELECT MESSAGE , USERNAME from CHATCOMPLETE where FROMID=? ORDER BY timestamp DESC LIMIT 1"; // change the `ORDER BY` to use whatever field you want to sort by
if (sqlite3_prepare_v2(_chatDB, query_stmt2, -1, &messageStatement, NULL) != SQLITE_OK)
{
NSLog(#"%s: prepare messageStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
else
{
if (sqlite3_bind_int(messageStatement, 1, userID) != SQLITE_OK)
{
NSLog(#"%s: bind userID %d failed: %s", __PRETTY_FUNCTION__, userID, sqlite3_errmsg(_chatDB));
}
while ((rc = sqlite3_step(messageStatement)) == SQLITE_ROW)
{
NSLog(#"LAST MESSAGE %#",[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)]);
}
if (rc != SQLITE_DONE)
{
NSLog(#"%s: step messageStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
sqlite3_finalize(messageStatement);
}
}
if (rc != SQLITE_DONE)
{
NSLog(#"%s: step userStatement failed: %s", __PRETTY_FUNCTION__, sqlite3_errmsg(_chatDB));
}
sqlite3_finalize(userStatement);
}
}
else
{
NSLog(#"%s: open %# failed", __PRETTY_FUNCTION__, _databasePath);
}
return messages;
Note, this code sample, in addition to my three points above, also:
Log errors using sqlite3_errmsg if sqlite3_prepare_v2 fails.
Added check on return codes from sqlite3_step, too, again logging sqlite3_errmsg if it fails.
Added log if sqlite3_open failed.
Use sqlite3_bind_int() rather building SQL using stringWithFormat. In this case, because userID is numeric, this isn't critical, but if ever using string values in your WHERE clauses, using the sqlite3_bind_text() function becomes critical, so I just wanted to show the pattern.
For example, look at your save routine and try saving a message that happens to have double quotation mark in it (e.g. I spoke with Bob and he says "hello" to you.). Your stringWithFormat construct will fail. If you use sqlite3_bind_text, it will solve that problem.
BTW, as you can see, when you add all of the proper validation of results, binding of values, etc., the code becomes a bit unwieldy. You might consider using FMDB, which greatly simplifies your SQLite Objective-C code.
I had debugged code but don't know why While statement is not executing . After putting NSlog I came to know it's mismatching the result. 101 and SQLITE_ROW is equal to 100.
But query has result. If I fetch Select * from table name its returning me result and while statement executes. If I fetch result
sql_stmt = [NSString stringWithFormat:#"SELECT * FROM DeviceType WHERE upper(TypeName) = upper('%#')", deviceType];
While statement never execute so please help. don't know where is the problem.
Here is the code:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:#"ClientDB.sqlite"];
NSString* sql_stmt = [self searchStringForLocalData];
BOOL found = NO;
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
const char* sql1 = [sql_stmt UTF8String];
sqlite3_stmt *statement;
NSNumber *typeCount;
typeCount = 0;
if (sqlite3_prepare_v2(database, sql1, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#" %d, %d ",sqlite3_step(statement),SQLITE_ROW);
while (sqlite3_step(statement) == SQLITE_ROW) {
// The second parameter indicates the column index into the result set.
int primaryKey1 = sqlite3_column_int(statement, 0);
NSNumber *typeId = [[NSNumber alloc] initWithInt:primaryKey1];
NSString *typeName =[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
NSString* sql_stmt1 = [NSString stringWithFormat:#"SELECT COUNT(*) FROM Devices WHERE DeviceTypeId =%d",primaryKey1];
const char *sql1 = [sql_stmt1 UTF8String];
sqlite3_stmt *statement;
NSNumber *typeCount;
typeCount = 0;
As already mentioned in a comment, the code calls sqlite3_step once for the NSLog, and then a second time in the condition of the while loop.
If your query returns exactly one record, the first sqlite3_step call will step to that record, and the second sqlite3_step call will then report (correctly) that no further results are available.
Just remove that NSLog call.
Alternatively, call sqlite3_step only once, and use the same return value for both the logging and the loop:
int rc;
...
while (1) {
rc = sqlite3_step(statement);
NSLog(#" %d, %d ", rc, SQLITE_ROW);
if (rc != SQLITE_ROW)
break;
...
}
if (rc != SQLITE_DONE)
NSLog(#"error: %s", sqlite3_errmsg(database));
Try to use the following syntax
while(sqlite3_step(stmt)!=SQLITE_DONE)
{
//do ur processing
for(i=0;i<NO_OF_COLS;i++)
{
char * tmp1=sqlite3_column_text(stmt,i);
if(tmp1!=NULL)
{
//use the value
}
else
{
//use a default
}
}
}
It shows that your table is totally empty. You may want to check your insert whether it works correctly. If you're using sqlite3_prepare_v2 to prepare your statement with some ? marks, remember to execute your query after all. Simply like this:
if(sqlite3_step(stmt) == SQLITE_DONE) NSLog(#"INSERTED");
else NSLog(#"NO INSERTED");
Note: It will display error only if your query is wrong, but not your prepared statement was executed or not.
I am deleting records from the database.and it is working fine .But it is crashing when there is no data in the database. The code is given Below
int noOfRecordsDeleted;
[self openDatabaseConnection];
// query = [NSString stringWithFormat:#"delete from %# where %#",query];
NSLog(#"del query=%#",query);
const char *sql = [query cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *statement = nil;
if(sqlite3_prepare_v2(dataBaseConnection,sql, -1, &statement, NULL)!= SQLITE_OK)
{
NSAssert1(0,#"error preparing statement",sqlite3_errmsg(dataBaseConnection));
}
else
{
int success = sqlite3_step(statement);
NSLog(#"%d",success);
}
sqlite3_finalize(statement);
noOfRecordsDeleted = sqlite3_changes(dataBaseConnection);
[self closeDatabaseConnection];
return noOfRecordsDeleted;
It is working fine. But if i am adding data i empty database it is crashing
[self openDatabaseConnection];
NSString *query;
query = [NSString stringWithFormat:#"insert into Userdetail(aboutMe,anniversary,areacode,birthdate,device_id,chat_id,emailid,gender ,image,last_login,latitute,longitude,Looking_For,mobilenumber,mobilenumber1 ,mobilenumber2,mood,name,password,place,profileviews,statusmessage) values ('%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#','%#')",aboutMe,anniversarydate,areacode,birthdate,
device_id,chat_id,email_id,gender,image,last_login,latitude,longitude,looking_for,mobilenumber,mobilenumber1,mobilenumber2,mood,name,password,place,profileviews,statusmessage];
NSLog(#"saveNewTemplateData query=%#",query);
const char *sql = [query cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *statement = nil;if(sqlite3_prepare_v2(dataBaseConnection,sql , -1, &statement, NULL)!= SQLITE_OK)
{
NSAssert1(0,#"error preparing statement",sqlite3_errmsg(dataBaseConnection));
}
else
{
sqlite3_step(statement);
}
sqlite3_finalize(statement);
[self closeDatabaseConnection];
above is the code
First of all check the Database is empty or not by using the following statement
if(sqlite3_column_text(statement, 0) != nil){//Data exists}
Then in the if method add the code to delete the dataBase.
It works fine.
query = [NSString stringWithFormat:#"delete from %# where %#",query];
what does this query means I think its the mistake of your query please doublecheck it
if the error persists programmatically check
by using if(sqlite3_column_text(statement, 0) != nil)
One issue I saw that you are calling sqlite3_finalize(statement); regardless the state of sqlite3_prepare_v2. You only need to call sqlite3_finalize if the sqlite3_prepare_v2 executed successfully.
Change that to:
if(sqlite3_prepare_v2(dataBaseConnection,sql, -1, &statement, NULL)!= SQLITE_OK)
{
NSAssert1(0,#"error preparing statement",sqlite3_errmsg(dataBaseConnection));
}
else
{
int success = sqlite3_step(statement);
NSLog(#"%d",success);
sqlite3_finalize(statement);
}
if (condition for check database empty (select * from table)){
}else{
//Perform Delete operation
}
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...