开发者

Assertion failure when trying to write (INSERT, UPDATE) to sqlite database on iPhone

开发者 https://www.devze.com 2022-12-22 00:19 出处:网络
I have a really frustrating error that I\'ve spent hours looking at and cannot fix. I can get data from my db no problem with this code, but inserting or updating gives me these errors:

I have a really frustrating error that I've spent hours looking at and cannot fix. I can get data from my db no problem with this code, but inserting or updating gives me these errors:


*** Assertion failure in +[Functions db_insert_answer:question_type:score:], /Volumes/Xcode/Kanji/Classes/Functions.m:129

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Error inserting: db_insert_answer:question_type:score:'

Here is the code I'm using:


    [Functions db_insert_answer:[[dict_question objectForKey:@"JISDec"] intValue] question_type:@"kanji_meaning" score:arc4random() % 100];

    //update EF, Next_question, n here
    [Functions db_update_EF:[dict_question objectForKey:@"question"] EF:EF];

To call these functions:



+(sqlite3_stmt *)db_query:(NSString *)queryText{
    sqlite3 *database = [self get_db];
        sqlite3_stmt *statement;
    NSLog(queryText);
    if (sqlite3_prepare_v2(database, [queryText UTF8String], -1, &statement, nil) == SQLITE_OK) {
    } else {
        NSLog(@"HMM, COULDNT RUN QUERY: %s\n", sqlite3_errmsg(database));  
    }
    sqlite3_close(database);
    return statement;
}
+(void)db_insert_answer:(int)obj_id question_type:(NSString *)question_type score:(int)score{
    sqlite3 *database = [self get_db];
        sqlite3_stmt *statement;
    char *errorMsg;
    char *update = "INSERT INTO Answers (obj_id, question_type, score, date) VALUES (?, ?, ?, DATE())";
    if (sqlite3_prepare_v2(database, update, -1, &statement, nil) == SQLITE_OK) { 
        sqlite3_bind_int(statement, 1, obj_id);
        sqlite3_bind_text(statement, 2, [question_type UTF8String], -1, NULL);
        sqlite3_bind_int(statement, 3, score);
    } 
    if (sqlite3_step(statement) != SQLITE_DONE){
        NSAssert1(0, @"Error inserting: %s", errorMsg); 
    }
    sqlite3_finalize(statement);
    sqlite3_close(database);
    NSLog(@"Answer saved");
}
+(void)db_update_EF:(NSString *)kanji EF:(int)EF{
    sqlite3 *database = [self get_db];
        sqlite3_stmt *statement;
    //NSLog(queryText);
    char *errorMsg;
    char *update = "UPDATE Kanji SET EF = ? WHERE Kanji = '?'";
    if (sqlite3_prepare_v2(database, update, -1, &statement, nil) == SQLITE_OK) {
        sqlite3_bind_int(statement, 1, EF);
        sqlite3_bind_text(statement, 2, [kanji UTF8String], -1, NULL);
    } else {
        NSLog(@"HMM, COULDNT RUN QUERY: %s\n", sqlite3_errmsg(database));  
    }
    if (sqlite3_step(statement) != SQLITE_DONE){
        NSAssert1(0, @"Error updating: %s", errorMsg); 
    }
    sqlite3_finalize(statement);
    sqlite3_close(database);
    NSLog(@"Update saved");
}

+(sqlite3 *)get_db{
    sqlite3 *database;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *copyFrom = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"/kanji_training.sqlite"];
    if([fileManager fileExistsAtPath:[self dataFilePath]]) { 
        //NSLog(@"DB FILE ALREADY EXISTS");
    } else {
        [fileManager copyItemAtPath:copy开发者_StackOverflowFrom toPath:[self dataFilePath] error:nil];
        NSLog(@"COPIED DB TO DOCUMENTS BECAUSE IT DIDNT EXIST: NEW INSTALL");
    }
    if (sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database); NSAssert(0, @"Failed to open database");
        NSLog(@"FAILED TO OPEN DB");
    } else {
        if([fileManager fileExistsAtPath:[self dataFilePath]]) {
            //NSLog(@"DB PATH:");
            //NSLog([self dataFilePath]);
        }
    }
    return database;
}

+ (NSString *)dataFilePath { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    return [documentsDirectory stringByAppendingPathComponent:@"kanji_training.sqlite"];
}

I really can't work it out! Can anyone help me?

Many thanks.


in db_insert_answer, you prepare your statement
if the prepare is SQLITE_OK, you bind your variables
however, regardless of preparation OK or not, you run the statement (which could be invalid)

you also do the same thing in db_update_EF

start there


char *update = "UPDATE Kanji SET EF = ? WHERE Kanji = '?'";

Replace it with

char *update = "UPDATE Kanji SET EF = ? WHERE Kanji = ?";

It's already a string. You don't need single quotes around that question mark.

0

精彩评论

暂无评论...
验证码 换一张
取 消