Objective-C API call with invalid database connection pointer

Viewed 3239

I am trying to open a SQLite3 database to be accessed at any time. I have created a DBModel class as well as a DBManager. The Model is NSString dbName, NSString dbPath, and SQLite3 db, and well as a BOOL dbOpened.

The reason I created the class is to help manage about a dozen different SQLite db's our previous developer created, and instead of creating, opening, closing removing these all over the place I decided to create the manager to handle all that in one place.

A quick example is:

if(sqlite3_prepare_v2(dbm.sitesDBModel.db,query , -1, &statement, NULL) == SQLITE_OK) {
    if(sqlite3_step(statement) == SQLITE_DONE) {
        //do stuff here
    }
}

dbm is the DBManager, siteDBModel is a DBModel related to our Site Data, query and statement are previously declared.

The error I get is:

API call with invalid database connection pointer.

I have seen this work when declaring the sqlite3 *db and opening it in the same code block but I want to prevent having to declare these variables in the different view controllers every time I want to run a query, which is again why I created the classes to handle these tasks.

DBModel

@interface DBModel : NSObject {
        NSString    *dbName;
        NSString    *dbTempName;
        NSString    *dbPath;
        NSString    *dbTempPath;
        sqlite3     *db;
        BOOL        dbOpen;
    }

    @property (nonatomic, retain) NSString  *dbName;
    @property (nonatomic, retain) NSString  *dbTempName;
    @property (nonatomic, retain) NSString  *dbPath;
    @property (nonatomic, retain) NSString  *dbTempPath;
    @property (atomic, readwrite) sqlite3   *db;
    @property (atomic, readwrite) BOOL      dbOpen;

DBManager

    @interface DBManager : NSObject {
        DBModel *sitesDBModel;
    }

    @property (nonatomic, retain) DBModel *sitesDBModel;

Implementation for DBManager

    -(void)createDB:(DBModel *)dbModel {
        NSFileManager *fileManager  = [NSFileManager defaultManager];
        BOOL success                = [fileManager fileExistsAtPath:dbModel.dbPath];

        if(!success) {
            NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbModel.dbName];
            [fileManager copyItemAtPath:databasePathFromApp toPath:dbModel.dbPath error:nil];
        }
    }

    -(void)openDB:(DBModel *)dbModel {
        sqlite3 *db = dbModel.db;
        if(sqlite3_open([dbModel.dbPath UTF8String], &db) == SQLITE_OK) {
            dbModel.dbOpen = YES;
        }
        else {
            dbModel.dbOpen = NO;
        }
    }
1 Answers

Your open method is what's causing the issue for you:

- (void)openDB:(DBModel *)dbModel {
    dbModel.db = nil;
    sqlite3 *db = dbModel.db;
    if(sqlite3_open([dbModel.dbPath UTF8String], &db) == SQLITE_OK) {
        dbModel.dbOpen = YES;
    }
    else {
        dbModel.dbOpen = NO;
    }
}

If you set a breakpoint right after the open call and po the addresses for db and dbModel.db you'll see that the dbModel.db isn't pointing to the open db connection:

(lldb) po db
0x00007fb242c1e500

(lldb) po dbModel.db
<nil>

You'll want point it to the open connection after establishing the connection pointer:

- (void)openDB:(DBModel *)dbModel {
    sqlite3 *db = nil;
    if(sqlite3_open([dbModel.dbPath UTF8String], &db) == SQLITE_OK) {
        dbModel.dbOpen = YES;
        // set our pointer to the open connection after establishing
        dbModel.db = db;
    }
    else {
        dbModel.dbOpen = NO;
    }
}

Now if you po they should match:

(lldb) po db
0x00007f877bd04a30

(lldb) po dbModel.db
0x00007f877bd04a30
Related