Exception while reading an empty table - iphone

Iam trying to read data from a table.
Initially it is empty. If i tried to read at that time it will cause an exception.
My code is given Below
-(NSMutableArray *) selectDataFrom:(NSString *) tableName
{
NSString *qsql = [NSString stringWithFormat:#"SELECT * FROM '%#' ",tableName];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( dataBase, [qsql UTF8String], -1, &statement, nil) == SQLITE_OK)
{
NSLog(#"INSIDE IF");
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"INSIDE WHILE");
// my code
}
}
return allData;
}
The first NSLog("INDISE IF"); is printed.
But the second one is not printing.
Mention some books to learn sqlite3 statements of iPhone [ eg: sqlite_prepare_v2();] not SQL
[ Sorry for my poor English]
THIS IS THE FULL CODE
-(NSMutableArray *) selectDataFrom:(NSString *) tableName
{
allData = [[NSMutableArray alloc] init];
NSString *qsql = [NSString stringWithFormat:#"SELECT * FROM '%#' ",tableName];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( dataBase, [qsql UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"REACHED 1");
myProgram = [[Programs alloc] init];
char *date = (char *) sqlite3_column_text(statement, 0);
myProgram.nss_Date = [[NSString alloc] initWithUTF8String:date];
char *type = (char *) sqlite3_column_text(statement, 3);
myProgram.nss_Type = [[NSString alloc]initWithUTF8String:type];
[nsma_allDonorsMA addObject:d_OneDonor];
}
}
else {
// NSLog(#"failed to select data");
}
return allData;
}

Try enabled breakpoints on exceptions and run your app in the debugger. It will show you exactly where you are calling objectAtIndex:. (It is not in the above code)

Where is your sqlite3_finalize() ??
You should release sqlite3_stmt structure in your sqlite3_prepare_v2 block, as following.
sqlite3_stmt *sql_stmt;
if (sqlite3_prepare_v2(...) == SQLITE_OK)
{
....
sqlite3_finalize(sql_stmt);
}

Related

"Database is locked" in delete operation in my sqlite

I have a function like this for delete table row in my apps, but I have an error that said "database is locked".
- (BOOL) deleteByCaption:(NSString *)registerCaption
{
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM tabelA WHERE CONTENT_CAPTION = \"%#\"", registerCaption];
const char *query_stmt = [querySQL UTF8String];
// NSMutableArray *resultArray = [[NSMutableArray alloc] init];
if(sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK){
if(sqlite3_step(statement) == SQLITE_ROW){
return YES;
}else{
NSLog(#"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
return NO;
}
}
sqlite3_reset(statement);
}
return NO;
}
You are missing sqlite3_finalize(). Look at //PUT HERE part in following code.
- (BOOL) deleteByCaption:(NSString *)registerCaption
{
BOOL isDeleted = NO; //EDIT
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:#"DELETE FROM tabelA WHERE CONTENT_CAPTION = \"%#\"", registerCaption];
const char *query_stmt = [querySQL UTF8String];
// NSMutableArray *resultArray = [[NSMutableArray alloc] init];
if(sqlite3_prepare_v2(database, query_stmt, -1, &statement, NULL) == SQLITE_OK){
if(sqlite3_step(statement) == SQLITE_ROW){
isDeleted = YES;
//return YES; //EDIT
}else{
NSLog(#"Error while creating delete statement. '%s'", sqlite3_errmsg(database));
//return NO; //EDIT
}
}
sqlite3_reset(statement);
sqlite3_finalize(statement); //PUT HERE
sqlite3_close(database); //EDIT
}
//return NO; //EDIT
return isDeleted; //EDIT
}
EDIT:
Try to set one variable to return.
Look at the edited portion in above code. Search for //EDIT.
In deleteByCaption function too, You are returning from function without closing data base.
You should write following statements before writing "RETURN YES" or "RETURN NO"
sqlite3_finalize(statement);
sqlite3_close(database);
Please check all functions where your have used sqlite3_open() function.
and make sure to write sqlite3_close() function before returning from that function.

My code snippet is leaking

The below code snippet leaks when i am trying the build and analyse thing.
What is the problem in this code , pls let me know
- ( NSString *) getSubCategoryTitle:(NSString*)dbPath:(NSString*)ID{
NSString *subCategoryTitle;
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
NSString *selectSQL = [NSString stringWithFormat: #"select sub_category_name from sub_categories where id = %#",ID];
NSLog(#"%# I am creashes here", selectSQL);
const char *sql_query_stmt = [selectSQL UTF8String];
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql_query_stmt, -1, &selectstmt, NULL) == SQLITE_OK)
{
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{
subCategoryTitle = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 0)];
}
}
sqlite3_finalize(selectstmt);
}
sqlite3_close(database);
return [subCategoryTitle autorelease];
}
You allocate instance into subCategoryTitle in a loop, but don't release the previous allocation.
subCategoryTitle = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 0)];
Either (auto)release it, or directly go to the last row, and avoid this while, as it doesn't make much sense.
Example for creating only last object:
char * col_text = NULL;
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{
col_text = sqlite3_column_text(selectstmt, 0);
}
if (col_text != NULL)
{
subCategoryTitle = [[NSString alloc] initWithUTF8String:col_text];
}

Select query not working in SQLite

i am running a method for containing select query, but compiled statement is not working the break point skips the line where it declares it and when i puts the cursor on it it shows no value, Here's the code i am using:
-(NSMutableArray *)GetAllPartsName
{
NSString *path = [self getDBPath];
// Open the database from the users filessytem
NSMutableArray *Parts=[[[NSMutableArray alloc]init]autorelease ];
if(sqlite3_open([path UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
NSString *sqlQuery = [NSString stringWithFormat:#"SELECT Parts_Name FROM Parts"];
NSLog(#"%#",sqlQuery);
const char *sqlStatement = [sqlQuery UTF8String];
//The break point skips the sqlite3_stmt.
sqlite3_stmt *compiledStatement;
//when i put the cursor over compiledStatement it shows no value
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
// Read the data from the result row
NSMutableDictionary *PositionDict=[[NSMutableDictionary alloc]init];
//setting the parts into dictionary
[PositionDict setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement,0)] forKey:#"Parts_Name"];
[Parts addObject:PositionDict];
NSLog(#"%#",PositionDict);
[PositionDict release];
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return Parts;
}
Try FMDattabase (https://github.com/ccgus/fmdb)
BASIC:
FMDatabase *_db = [[FMDatabase databaseWithPath:[[self class] databaseFilePath]] retain];
[_db open];
NSMutableArray *emails = [[NSMutableArray alloc] init];
NSString * query = [NSString stringWithFormat:#"SELECT `email` FROM `email`"];
FMResultSet * result = [_db executeQuery:query];
while ([result next])
{
[emails addObject:[result stringForColumn:#"email"]];
}
return [emails autorelease];

not able to insert record in table in objective c

I made iPad application in which,
I want to insert record into database table, but I am unable to do the same.
here is my code snippet,
-(void) insertRecordIntoTableNamed: (NSString *) symbol{
NSString *sql = [NSString stringWithFormat:#"INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('%#',datetime())",symbol];
NSLog(#"sql=%#",sql);
char *err;
if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK)
{
sqlite3_close(db);
NSAssert(0, #"Error updating table.");
}
}
my NSLog shows:
sql=INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('PATNI',datetime())
this statement is correct, but i am unable to see VALUES PATNI and datetime() in my database table
here is rest of the code,
NSString *filePahs = Nil;
-(NSString *) filePath {
filePahs=[[NSBundle mainBundle] pathForResource:#"companymaster" ofType:#"sql"];
NSLog(#"path=%#",filePahs);
return filePahs;
}
result of above method is:
path=/Users/krunal/Library/Application Support/iPhone Simulator/5.0/Applications/9FF61238-2D1D-4CB7-8E24-9AC7CE9415BC/iStock kotak.app/companymaster.sql
-(void) openDB {
//---create database---
if (sqlite3_open([[self filePath] UTF8String], &db) != SQLITE_OK )
{
sqlite3_close(db);
NSAssert(0, #"Database failed to open.");
}
}
-(void) getAllRowsFromTableNamed: (NSString *) tableName {
//---retrieve rows---
NSString *qsql = #"SELECT * FROM recentquotes";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2( db, [qsql UTF8String], -1, &statement, nil) ==
SQLITE_OK) {
NSLog(#"b4 while");
while (sqlite3_step(statement) == SQLITE_ROW)
{
char *field1 = (char *) sqlite3_column_text(statement, 0);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
[recentqotarray addObject:field1Str];
[field1Str release];
}
//---deletes the compiled statement from memory---
sqlite3_finalize(statement);
NSLog(#"recentqotarray=%#",recentqotarray);
}
}
edit
i wrote this, and when i checked my log i got like this, "in find data" , i didn't got my sql=...
- (void) finddata
{
NSString *databasePath;
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
NSLog(#"in finddata");
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: #"SELECT * FROM recentquotes"];
NSLog(#"sql=%#",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"Inside recent quote table");
char *field1 = (char *) sqlite3_column_text(statement, 0);
NSLog(#"Column name=%s",field1);
NSString *field1Str = [[NSString alloc] initWithUTF8String: field1];
[recentqotarray addObject:field1Str];
NSLog(#"array=%#",recentqotarray);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
}
Thanks In Advance
In your:
NSString *sql = [NSString stringWithFormat:#"INSERT INTO recentquotes ('symbol', 'dt_tm') VALUES ('%#',datetime())",symbol];
Instead of '%#' try using \"%#\" , and check if it inserts into your db.
EDIT:
I've been working on DB a lot lately, and i've been able to successfully insert data in my sqlite, i'll write down what i use check if it helps:
NSArray*dirPath;
NSString*docDir;
dirPath=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docDir=[dirPath objectAtIndex:0];
databasePath=[docDir stringByAppendingPathComponent:#"example.sqlite"];
BOOL success;
NSFileManager*fm=[NSFileManager defaultManager];
success=[fm fileExistsAtPath:databasePath];
if(success)
{
NSLog(#"Already present");
}
NSString*bundlePath=[[NSBundle mainBundle] pathForResource:#"example" ofType:#"sqlite"];
NSError*error;
success=[fm copyItemAtPath:bundlePath toPath:databasePath error:&error];
if(success)
{
NSLog(#"Created successfully");
}
const char*dbPath=[databasePath UTF8String];
if(sqlite3_open(dbPath, &myDB)==SQLITE_OK)
{
NSString*insertSQL=[NSString stringWithFormat:#"insert into extable (name) values (\"%#\")",[nametextField.text]];
const char*insertStmt=[insertSQL UTF8String];
char *errmsg=nil;
if(sqlite3_exec(myDB, insertStmt, NULL, NULL, &errmsg)==SQLITE_OK)
{
NSLog(#"ADDED!");
}
sqlite3_close(myDB);
}

SQLite sqlite3_prepare_v2 no error but not ok neither

Hey guys, I'm just playing around with SQLite so this is new for me. I've got a view in which persons data can be both saved and found. The save-function and find-function work perfectly. Now, I've got a new view with a tableView in it. I want to get all the persons in the contacts-table and fill the list with it.
Untill now, I've got:
-(void)viewWillAppear:(BOOL)animated {
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSLog(#"Opened DB");
NSString *querySQL = [NSString stringWithFormat:#"SELECT name FROM contacts"];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"could not prepare statement: %s\n", sqlite3_errmsg(contactDB));
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
//if (sqlite3_step(query_stmt) == SQLITE_DONE)
{
//NSLog(#"SQLite OK");
NSLog(#"SQLite ok");
//if (sqlite3_step(statement) == SQLITE_ROW)
//{
while(sqlite3_step(statement) == SQLITE_ROW) {
NSLog(#"SQLite ROW");
NSString *person = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[personsList addObject:person];
}
//} else {
// NSLog(#"Emtpy list");
//}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
}
NSLog(#"Calling reload");
NSLog(#"%#", personsList);
[tabelView reloadData];
}
This is all in viewWillAppear. When the view is loaded and done, the log says:
2011-05-06 10:45:26.976 database[1412:207] Opened DB
2011-05-06 10:45:26.978 database[1412:207] could not prepare statement: not an error
2011-05-06 10:45:26.979 database[1412:207] Calling reload
2011-05-06 10:45:26.979 database[1412:207] (
)
So it seems the statement isn't an error, but sqlite3_prepare_v2 isn't SQL_OK after all. Any help?
EDIT: In the previous view, the statement for creating a person is: #"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%#\", \"%#\", \"%#\")", name.text, address.text, phone.text];
The statement for finding someone is: #"SELECT address, phone FROM contacts WHERE name=\"%#\"", name.text];
These two statements work and the data is displayed.
#joetjah I used your code to fetch the results and it worked fine
2011-05-06 16:03:00.076 SQLiteDemo[6454:207] Opened DB
2011-05-06 16:03:09.550 SQLiteDemo[6454:207] could not prepare statement: not an error
2011-05-06 16:03:24.685 SQLiteDemo[6454:207] SQLite ok
2011-05-06 16:03:26.229 SQLiteDemo[6454:207] SQLite ROW
2011-05-06 16:03:28.254 SQLiteDemo[6454:207] SQLite ROW
2011-05-06 16:03:34.461 SQLiteDemo[6454:207] Calling reload
2011-05-06 16:03:35.009 SQLiteDemo[6454:207] (
rahul,
sqlite
)
-(void)testFunction{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
sqlite3 *contactDB;
NSMutableArray *personsList = [[NSMutableArray alloc ] initWithCapacity:0];
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSLog(#"Opened DB");
NSString *querySQL = [NSString stringWithFormat:#"SELECT name FROM contacts"];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"could not prepare statement: %s\n", sqlite3_errmsg(contactDB));
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
//if (sqlite3_step(query_stmt) == SQLITE_DONE)
{
//NSLog(#"SQLite OK");
NSLog(#"SQLite ok");
//if (sqlite3_step(statement) == SQLITE_ROW)
//{
while(sqlite3_step(statement) == SQLITE_ROW) {
NSLog(#"SQLite ROW");
NSString *person = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[personsList addObject:person];
}
//} else {
// NSLog(#"Emtpy list");
//}
sqlite3_finalize(statement);
}
sqlite3_close(contactDB);
}
NSLog(#"Calling reload");
NSLog(#"%#", personsList);
//[tabelView reloadData];
}
You can compare the code, The probable point of failure might be
1] data not being saved properly and hence nothing is fetched.
2] databasePath being set to blank (which I doubt as you get Open Db log)
The table contact is created using "CREATE TABLE contacts (name text, age integer)"
try this once and let me know if it works.
Try this,
-(void)viewWillAppear:(BOOL)animated {
// Override point for customization after app launch.
// Setup some globals
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:#"contacts.db"];
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
NSLog(#"Opened DB");
NSString *querySQL = [NSString stringWithFormat:#"SELECT name FROM CONTACTS"];
const char *query_stmt = [querySQL UTF8String];
NSLog(#"could not prepare statement: %s\n", sqlite3_errmsg(contactDB));
if (sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
NSLog(#"SQLite ok");
while(sqlite3_step(statement) == SQLITE_ROW) {
NSLog(#"SQLite ROW");
NSString *person = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
[personsList addObject:person];
}
sqlite3_finalize(statement);
}
else
{
//NSLog(#"could not prepare statement: %s\n", sqlite3_errmsg(statement));
}
sqlite3_close(contactDB);
}
NSLog(#"Calling reload");
NSLog(#"%#", personsList);
[tabelView reloadData];
}
I used const char *dbpath = [databasePath UTF8String];, but I forgot to put the following code above it:
// Get the documents directory
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"contacts.db"]];
const char *dbpath = [databasePath UTF8String];
This worked for me:
create the table in your didload functions and then add this in (assuming you have declared the other table view functions):
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
var selectStatement: OpaquePointer? = nil
let selectSql = "select * from Inventory where ID = \((indexPath.row + 1))"
if sqlite3_prepare_v2(Database.database.sqliteDB, selectSql, -1, &selectStatement, nil) == SQLITE_OK{
if sqlite3_step(selectStatement) == SQLITE_ROW {
let nameItem = sqlite3_column_text(selectStatement, 1)
let price = sqlite3_column_double(selectStatement, 2)
let quantity = sqlite3_column_int(selectStatement, 3)
let nameString = String(cString: nameItem!)
let priceString = String(format: "%.1f",price)
let quantityString = String(quantity)
cell.itemName.text = nameString
cell.itemPrice.text = priceString
cell.itemQuantity.text = quantityString
}
}
return cell
}