Assertion failure when trying to write (INSERT, UPDATE) to sqlite database on iPhone
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.
精彩评论