SQLite sqlite3_prepare_v2 no error but not ok neither - iphone

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
}

Related

sqlite3_prepare_v2 statement is not SQLITE_OK and I don't know why

I have this code in my viewWillAppear method:
sqlite3 *database;
if (sqlite3_open([[self dataFilePath] UTF8String], &database)
!= SQLITE_OK) {
sqlite3_close(database);
NSAssert(0, #"Failed to open database");
}
sqlite3_stmt *statement;
//why is this if statement failing?
if (sqlite3_prepare_v2(database, [sqlStatement UTF8String],
-1, &statement, nil) == SQLITE_OK) {
It passes the first if statement without entering (which is good). The 2nd if statement is the problem.
The sqlStatement is in the form of SELECT * FROM food WHERE foodType = 'fruit'
I don't understand why it's not getting into the if statement. Any help would be appreciated.
The problem ended up not being in the code, but in the way that I exported the sqlite file. It was a series on INSERT statements, not an actual table.
and make changes according to ur requirement...
-(void) readDataFromDatabase
{
chapterAry = [[NSMutableArray alloc] init];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:#"QuotesApp.sqlite"];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK)
{
const char *sqlStatement ="select * from MsExcelTutorial";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(sqlite3_step(compiledStatement)==SQLITE_ROW)
{
NSNumber *chapterId = [NSNumber numberWithInt:(int)sqlite3_column_int(compiledStatement, 0)];
NSString *chapter = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *link = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *bookmark = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSMutableDictionary *dic = [[NSMutableDictionary alloc]initWithObjectsAndKeys:chapterId,#"chapterId",chapter,#"chapter",link,#"link",bookmark,#"bookmark", nil];
[chapterAry addObject:dic];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
NSString *DBPath = [ClsCommonFunctions GetDatabasePath];
if ([self OpenDBWithPath:DBPath])//Method to open database connection
{
//filesDB is database object
// Setup the SQL Statement and compile it for faster access
const char *sqlStatement = "select fileID,filePath from tblFiles where isUploadPending =1";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(filesDB, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW)
{
// u Need to get data from database...
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
sqlite3_close(filesDB);
}
go through it it will work

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);
}

Exception while reading an empty table

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);
}