views:

36

answers:

1

Hi, I'm trying to use sqlite in a 'data services' class like below. I keep getting an error code 1 when calling 'sqlite3_prepare_v2'. The logs certainly back up that the database is getting opened before my recipeNames function is called. I'm so stumped! Is it a memory management thing with the sqlite3 *db ? Eg is it getting freed when i don't want it to?

I'm certain the code is OK otherwise, because if i put the sqlite_open in the recipeNames function, it works great. It's just if i try to open it in the init method it fails. Thanks a lot guys.

My header:

#import <Foundation/Foundation.h>
#include <sqlite3.h>


@interface DataServices : NSObject {
    sqlite3 *db;
    int dbrc;
}

- (NSMutableArray *) recipeNames;

@end

Implementation file:

#import "DataServices.h"
#import "MenuMakerAppDelegate.h"
#include <sqlite3.h>

@implementation DataServices

- (id)init {
    [super init];

    // my init stuff here

    // Get the database name
    const char *dbPathUtf8 = [((MenuMakerAppDelegate*)[UIApplication sharedApplication].delegate).dbFilePath UTF8String];
    // Open the database
    NSLog(@"opening db");
    sqlite3_open (dbPathUtf8, &db);
    NSLog(@"opened db");

    return self;
}

- (void)dealloc {
    // My dealloc stuff here
    NSLog(@"Closing DB");
    sqlite3_close(db);
    [super dealloc];
}

- (NSMutableArray *) recipeNames {
    // Create the empty array to return
    NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease];
    // The SQL
    NSString *sql = @"select recipe from recipes";
    const char *sqlUtf8 = [sql UTF8String];
    // Make the prepared statement (like C# SqlCommand)
    sqlite3_stmt *dbps;
    dbrc=sqlite3_prepare_v2(db, sqlUtf8, -1, &dbps, NULL); // FAILS HERE !!!
    if (dbrc) NSLog(@"Prepare!!! %d", dbrc);
    // Loop thru rows
    while (sqlite3_step(dbps) == SQLITE_ROW) {
        NSString *recipe = [NSString stringWithUTF8String:(char*)sqlite3_column_text(dbps,0)];
        [arr addObject:recipe];
    }
    // Get rid of the command
    sqlite3_finalize(dbps);
    // Return the array that was autoreleased before
    return arr;
}

@end
+2  A: 

On a hunch:

NSLog(@"opening db %s", dbPathUtf8);
int result = sqlite3_open(dbPathUtf8, &db);
NSLog(@"sqlite3_open returned %d", result);

I'm betting that dbPathUtf8 is null and that sqlite3_open is returning an error. 1 is SQLITE_ERROR (SQL error or missing database), which probably means db is NULL.

tc.
No, i'm certain that's not it: i copied the dbPathUtf8=... and sqlite3_open... lines to the top of the recipenames function and it opened just fine.
Chris
I tried your code anyway, and it outputted that the return code was zero, which i believe means it's OK.
Chris
However... i also tried logging the dbPathUtf8 - and it was null. Maybe that's the problem? Maybe i can't get the path from the app delegate as early as my init function? Maybe it only becomes available later?
Chris
Ah figured it out! The problem was that my app delegate's "didFinishLaunchingWithOptions" was being called *after* the view's "viewDidLoad", so the path wasn't ready yet.
Chris