0
votes

I am stuck in iOS application that works on SQLite. I have created a Coffee table with different types of coffee names and prices along with the coffee ID which acts as the primary key. In SQLite I could run the SQL queries and got the correct answers. But while getting the coffee names in iOS table view, I got nothing except the blank table and section title. While debugging the code I found that while(sqlite3_step(selectstmt) == SQLITE_ROW) is not working as sqlite3_step(selectstmt) returns 101 value (i.e. SQLITE_DONE) instead of SQLITE_ROW (i.e value 100) even if I tried with sqlite3_reset() before executing sqlite3_step(). I could not figure out how to solve it. I need your help.

Here is my code of coffee.m

#import "Coffee.h"

#import "SQLAppDelegate.h"

static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
static sqlite3_stmt *addStmt = nil;


@implementation Coffee

@synthesize coffeeID, coffeeName, price, isDirty, isDetailViewHydrated;

- (void) dealloc {

    [price release];
    [coffeeName release];
    [super dealloc];
}

+ (void) getInitialDataToDisplay:(NSString *)dbPath{


    SQLAppDelegate *appDelegate = (SQLAppDelegate *)[[UIApplication sharedApplication] delegate];

    if(sqlite3_open([dbPath UTF8String], &database)==SQLITE_OK){

        const char *sql = "select CoffeeID, CoffeeName from Coffee";

        sqlite3_stmt *selectstmt = nil;

        if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL)== SQLITE_OK){
            sqlite3_reset(selectstmt);
            //NSLog(@"Macro %d",sqlite3_step(selectstmt));

               while(sqlite3_step(selectstmt) == SQLITE_ROW){

                NSInteger primaryKey = sqlite3_column_int(selectstmt,0);
                NSLog(@"The P key is %d:",primaryKey);
                Coffee *coffeeObj = [[Coffee alloc] initWithPrimaryKey:primaryKey];
                coffeeObj.coffeeName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
                coffeeObj.isDirty = NO;
                [appDelegate.coffeeArray addObject:coffeeObj];
                [coffeeObj release];
            }
        }
    }
    else 
        sqlite3_close(database);
}

- (id) initWithPrimaryKey:(NSInteger ) pk{

    [super init];
    coffeeID = pk;
    NSLog(@"%d",coffeeID);
    isDetailViewHydrated = NO;

    return self;
}

+ (void)finalizeStatements {

    if(database) 
        sqlite3_close(database);
}

@end

+++++++++++++++++++++++++++++++++++++++++RootViewController.m++++++++++++++++++

#import "RootViewController.h"

#import "Coffee.h"

@implementation RootViewController

#pragma mark -

#pragma mark View lifecycle

- (void)viewDidLoad { [super viewDidLoad];

self.navigationItem.rightBarButtonItem = self.editButtonItem;

appDelegate = (SQLAppDelegate *)[[UIApplication sharedApplication]delegate];

self.title = @"Name List";//Coffee List;


// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;

}

#pragma mark -

#pragma mark Table view data source

// Customize the number of sections in the table view.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

return 1;

}

// Customize the number of rows in the table view.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

NSLog(@"Rows %d",[appDelegate.coffeeArray count]);

return [appDelegate.coffeeArray count];

}

// Customize the appearance of table view cells.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];

}

// Configure the cell.

Coffee *coffeeObj = [appDelegate.coffeeArray objectAtIndex:indexPath.row];

cell.textLabel.text = coffeeObj.coffeeName;

return cell;

}

++++++++++++++++++++++++++++++++++++++++++ SQLAppDelegate.m +++++++++++++++++++++++++++++++++++

#import "SQLAppDelegate.h"

#import "RootViewController.h"

#import "Coffee.h"

@implementation SQLAppDelegate

@synthesize window;

@synthesize navigationController;

@synthesize coffeeArray;

#pragma mark -

#pragma mark Application lifecycle

- (void) copyDatabaseIfNeeded {

NSFileManager *fileManager = [NSFileManager defaultManager];

NSError *error;

NSString *dbPath = [self getDBPath];

// NSLog(@"%@",dbPath);

BOOL success = [fileManager fileExistsAtPath:dbPath];

NSLog(@"%d",success);

if(!success){

    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"CoffeeDetail.sqlite"];

    success =[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];

    if(!success)
        NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);

}

}

- (NSString *)getDBPath{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *documentDir = [paths objectAtIndex:0]; 

//NSLog(@"dbpath %@",[documentDir stringByAppendingPathComponent:@"SQL.sqlite"]);

return [documentDir stringByAppendingPathComponent:@"CoffeeDetail.sqlite"];

}

- (void) removeCoffee:(Coffee *)coffeeObj{

//Delete from DataBase

[coffeeObj deleteCoffee];

//Delete from the array

[coffeeArray removeObject:coffeeObj];

}

- (void)applicationDidFinishLaunching:(UIApplication *)application {

[self copyDatabaseIfNeeded];

NSMutableArray *tempArray =[[NSMutableArray alloc]init];

self.coffeeArray = tempArray;

[tempArray release];

[Coffee getInitialDataToDisplay:[self getDBPath]];

NSLog(@"Array =%@", self.coffeeArray);  

[window addSubview:[navigationController view]];

[window makeKeyAndVisible];

}

- (void) deleteCoffee{

        if(deleteStmt == nil){

        const char *sql = "delete from Coffee where coffeeID = ?";

       if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)

        NSAssert1(0,@"Error while creating the delete Statement. '%s'",    sqlite3_errmsg(database));
         }

            sqlite3_bind_int(deleteStmt, 1, coffeeID);

        if(SQLITE_DONE != sqlite3_step(deleteStmt))
                NSAssert1(0,@"Error while deleting. '%s'", sqlite3_errmsg(database));

        sqlite3_reset(deleteStmt);

}

1

1 Answers

0
votes

I think in deleteCoffee you're trying to use a variable that isn't set (database).

In my sqlite apps I have this method:

-(sqlite3 *) getNewDBConnection{
    sqlite3 *newDBconnection;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"data.sqlite"];
    // Open the database. The database was prepared outside the application.
    if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {

        //NSLog(@"Database Successfully Opened");

    } else {
        NSLog(@"Error in opening database");
    }

    return newDBconnection; 
}

and then in the methods that access the DB, I have something like:

- (void) deleteCoffee{
        sqlite3 *database = [self getNewDBConnection]; //see this line
        if(deleteStmt == nil){

        const char *sql = "delete from Coffee where coffeeID = ?";

       if(sqlite3_prepare_v2(database, sql, -1, &deleteStmt, NULL) != SQLITE_OK)

        NSLog(@"Error while creating the delete Statement. '%s'",    sqlite3_errmsg(database));
         }

            sqlite3_bind_int(deleteStmt, 1, coffeeID);

        if(SQLITE_DONE != sqlite3_step(deleteStmt))
                NSLog(@"Error while deleting. '%s'", sqlite3_errmsg(database));

        sqlite3_reset(deleteStmt);

}