Thanks for the advice.
I replaced the separate CREATE and INSERT statements with:
CREATE TABLE main.customer AS SELECT * FROM default_db.customer;
as you suggested. No issues.
When I try to create the unique index on this table, however, I get the same SQLITE_CANTOPEN result code. I had to remove the 'main.' prefix because I was getting a syntax error.
Another thing I've noticed is that I don't get this result code when running on the simulator, only on the device.
I've included code below. Each of these methods is in a custom class. I begin the update from the app delegate by creating an instance of the custom class and sending it performUpdate101 w/ the database as an argument. Could this be what's causing my problem?
- (void)performUpdate101:(sqlite3 *)db {
database = db;
[self attachDefaultDBToUserDB];
[self beginTransaction];
[self copyDataToCustomerTable];
[self createUniqueIndexOnCustomerTable];
[self commitTransaction];
[self detachDefaultDBFromUserDB];
}
- (void)attachDefaultDBToUserDB {
// PREPARE
if (attachdefaultDB_to_userDBstmt == nil) {
// Get path to default database
NSString *defaultDBPath = [[NSBundle mainBundle] resourcePath];
defaultDBPath = [defaultDBPath stringByAppendingPathComponent:kDB_Filename];
NSString *tempString = [NSString stringWithFormat:@"ATTACH DATABASE '%@' AS db_default", defaultDBPath];
const char *sql = (char *)[tempString UTF8String];
if (sqlite3preparev2(database, sql, -1, &attachdefaultDB_to_userDBstmt, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// STEP
NSInteger rc = sqlite3step(attach_defaultDB_to_userDBstmt);
if(rc != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to step through statement with message '%@'.", sqlite3_errmsg(database));
}
// RESET
sqlite3reset(attach_defaultDB_to_userDBstmt);
}
- (void)beginTransaction {
// PREPARE
if (begintransactionstmt == nil) {
const char *sql = "BEGIN TRANSACTION";
if (sqlite3preparev2(database, sql, -1, &begintransactionstmt, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// STEP
NSInteger rc = sqlite3step(begin_transactionstmt);
if(rc != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to step through statement with message '%s'.", sqlite3_errmsg(database));
}
// RESET
sqlite3reset(begin_transactionstmt);
}
- (void)copyDataToCustomerTable {
// PREPARE
if (copydata_to_customer_tablestmt == nil) {
const char *sql = "CREATE TABLE main.customer AS SELECT * FROM db_default.customer";
if (sqlite3preparev2(database, sql, -1, ©data_to_customer_tablestmt, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// STEP
NSInteger rc = sqlite3step(copy_data_to_customer_tablestmt);
if(rc != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to step through statement with message '%s'.", sqlite3_errmsg(database));
}
// RESET
sqlite3reset(copy_data_to_customer_tablestmt);
}
- (void)createUniqueIndexOnCustomerTable {
// PREPARE
if (createunique_index_on_customer_tablestmt == nil) {
const char *sql = "CREATE UNIQUE INDEX prime ON customer(name, phone, zip)";
if (sqlite3preparev2(database, sql, -1, &createunique_index_on_customer_tablestmt, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// STEP
// This is where I get SQLITE_CANTOPEN (rc = 14)
NSInteger rc = sqlite3step(create_unique_index_on_customer_tablestmt);
if(rc != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to step through statement with message '%s'.", sqlite3_errmsg(database));
}
// RESET
sqlite3reset(create_unique_index_on_customer_tablestmt);
}