I'm having two crashes show up in my logs using the following code to insert into my SQLite DB - the code works perfectly most of the time however clearly there is a something wrong that's causing the crash.
It crashes on either sqlite3_last_insert_rowid or sqlite3_close with EXC_BAD_ACCESS (I hold a reference to the SMSDatabase and it's in a singleton not sure why it would be deallocated) and SIGABRT (memory issue?)
- (NSInteger)query:(NSString *)query {
NSInteger lastRowID = 0;
if (sqlite3_open([self.databasePath UTF8String], &smsDatabase) == SQLITE_OK)
{
sqlite3_stmt *statement = nil;
const char *sql = [query UTF8String];
if (sqlite3_prepare_v2(smsDatabase, sql, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_step(statement) == SQLITE_DONE)
{
lastRowID = sqlite3_last_insert_rowid(smsDatabase);
}
}
sqlite3_finalize(statement);
}
sqlite3_close(smsDatabase);
return lastRowID;
}
Where am I going wrong?
sqlite3_close(smsDatabase); - isn't this outside your if statement, which means you are closing a database which may have never been opened ?
Related
I am using SQLITE with my iPhone App. After Inserting the values in the detailedViewController, I am reloading the data from the database in the masterViewController viewWillAppear method. However I can't get the newly updated row there unless I restart the application.
I am finalizing the complied statement and closing the database after INSERT.
sqlite3_finalize(compiledStatement);
sqlite3_close(database);
Any pointers as to where I might be doing something wrong?
if(sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "SELECT * FROM MYCAR1";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
//...getting data from compiled statements...
MyCar *car=[[MyCar alloc] initWithVIN:vin.intValue andMake:make andModel:model andYear:year andColor:color andImageData:image];
[myArray addObject:car];
}
}
sqlite3_finalize(compiledStatement);
carList=myArray;
}
sqlite3_close(database);
[self.tableView reloadData];
I have added exact code for selecting, which is working for me. Try to compare this with your code and figure out the error.
sqlite3 *database;
if(sqlite3_open([databasePath UTF8String], &database)==SQLITE_OK)
{
NSString *querySql=[NSString stringWithFormat:#"Select * from xxx"];
const char *sqlStatement=[querySql UTF8String];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the your array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
//get the data from db here
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
I can receive the data from .sql file(sqlite) in iOS5 , But in ios6. The app is getting hang..
If the query is select * from Table then works perfectly
If query is select *from Table order by ID DESC then the app is getting hang
some times the app hang in (sqlite3_open([dbPath UTF8String],&db) == SQLITE_OK)
some times hangs in
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
}
Finalize the statements and Close the connection properly each you perform an operation, then you should be fine with the sqlite. If the statements are not finalized then you get to states like SQLITE_BUSY,SQLITE_LOCKED which you need to handle. If the app is hanging that means your main thread is blocked. Following is a sample sqlite operation.
-(int)keyIdForImgId:(int)ImgId
{
#synchronized(self)
{
int keyId=0;
sqlite3 *database=nil;
if (sqlite3_open([[self getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "SELECT keyId From SomeTableName WHERE imageId=?";
sqlite3_stmt *selectstmt=nil;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
sqlite3_bind_int(selectstmt, 1, ImgId);
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{
keyId = sqlite3_column_int(selectstmt, 0);
}
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
return keyId;
}
}
i am using this code to insert names to table,i have a problem that after 150 +/- names the app crash with this log:
Received memory warning. Level=1
Received memory warning. Level=2
this is the code,did i done something wrong?
if (sqlite3_open([dataPath UTF8String], &database) == SQLITE_OK) {
for (int i = 0 ; i < count; i++) {
sqlite3_stmt *insertStmt = nil;
NSString *name = [song valueForProperty:MPMediaItemPropertyTitle];
if(insertStmt == nil)
{
NSString *statement = [NSString stringWithFormat:#"INSERT INTO Songs (name) VALUES (?)"];
const char *insertSql = [statement UTF8String];
if(sqlite3_prepare_v2(database, insertSql, -1, &insertStmt, NULL) != SQLITE_OK){
NSLog(#"Error while creating insert statement.");
insertStmt = nil;
continue;
}
sqlite3_bind_text(insertStmt, 1, [name UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(insertStmt)){
NSLog(#"Error while inserting data.");
insertStmt = nil;
continue;
}
else{}
sqlite3_reset(insertStmt);
insertStmt = nil;
}
[delegate IPodLibraryFinishEntity:self];
}
sqlite3_close(database);
}
Use instruments to check for memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. Use Heapshot in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically there method is to run Instruments allocate tool, take a heapshot, run an intuition of your code and another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on on (you have to stop recording to set the option). Cause the picker to run, stop recording, search for there ivar (datePickerView), drill down and you will be able to see where all retains, releases and autoreleases occurred.
Your code is not optimal. You should place all prepare methods before the loop.
if (sqlite3_open([dataPath UTF8String], &database) == SQLITE_OK) {
sqlite3_stmt *insertStmt = nil;
NSString *name = [song valueForProperty:MPMediaItemPropertyTitle];
if(insertStmt == nil) {
NSString *statement = [NSString stringWithFormat:#"INSERT INTO Songs (name) VALUES (?)"];
const char *insertSql = [statement UTF8String];
if(sqlite3_prepare_v2(database, insertSql, -1, &insertStmt, NULL) != SQLITE_OK){
NSLog(#"Error while creating insert statement.");
insertStmt = nil;
return;
}
}
for (int i = 0 ; i < count; i++) {
sqlite3_bind_text(insertStmt, 1, [name UTF8String], -1, SQLITE_TRANSIENT);
if(SQLITE_DONE != sqlite3_step(insertStmt)){
NSLog(#"Error while inserting data.");
continue;
}
else{}
sqlite3_clear_bindings(insertStmt); //release bindings
sqlite3_reset(insertStmt);
[delegate IPodLibraryFinishEntity:self];
}
sqlite3_close(database);
}
Before starting each Insert statement use sqlite3_open and after execution of query put sqlite3_close statement. So that it wont make database object busy anymore after each Insert query execution.
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)
Help please :-)
Following code is supposed to delete a record. It seems to execute OK, no error message and the NSLog shows "Record Deleted" message. However the record is not deleted. I have used Terminal to check and indeed the deleted record is still there. The puzzling part is that I have very similar code to add and count records and they all seem to work... I am not an SQL expert, so I am hoping that an expert in this crowd can see the error.
Thanks
(void) deleteRecord
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &wfDataBase) == SQLITE_OK)
{
NSLog(#"About to Delete Record %d",currentID);
NSString *querySQL = [NSString stringWithFormat: #"DELETE from wfDataBase WHERE ID = %d", currentID];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(wfDataBase, query_stmt, -1, &statement, NULL) == SQLITE_OK)
l_status.text = #"Record Deleted";
else
l_status.text = #"Can't Delete";
sqlite3_finalize(statement);
sqlite3_close(wfDataBase);
}
}
Are you sure you have evaluated (sqlite3_step(statement )) the compiled statement (sqlite3_prepare_v2(wfDataBase, query_stmt, -1, &statement, NULL)) before destroying it (sqlite3_finalize(statement))?
Note: I'm not an expert on SQLite (indeed I don't know anything about SQLite) but I guess this is the cause of the problem.