iOS SQLite FMDB Transactions.. Correct usage?
You could also use FMDatabaseQueue to handle your transactions, which is part of fmdb:
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) { [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; if (whoopsSomethingWrongHappened) { *rollback = YES; return; } // etc… [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];}];
I wouldn't try to do the second update if the first failed.
bool ret = false;[fmdb beginTransaction];ret = [fmdb executeUpdate:@"query1"];if (ret){ ret = [fmdb executeUpdate:@"query2"]; if (!ret) { // report error 2 }}if(ret) { if (![fmdb commit]) { // panic! }}else{ if (![fmdb rollback]) { // panic! }}
For paranoid robustness you should have a try ... catch block in case anything throws an exception. If you do, you can use it to your advantage.
[fmdb beginTransaction];@try{ if (![fmdb executeUpdate:@"query1"]) { // report error @throw someExcpetion; } if (![fmdb executeUpdate:@"query2"]) { // report error @throw someExcpetion; } [fmdb commit]}@catch(NSException* e){ [fmdb rollback]; // rethrow if not one of the two exceptions above}
Swift way:
let queue = FMDatabaseQueue(path: databaseURL.path!)queue.inTransaction() { db, rollback in result = db.executeUpdate("INSERT INTO client VALUES (NULL, ?)", client.name ?? "") if result { client.ID = Int(db.lastInsertRowId()) } else { rollback.initialize(true) print("\(__FUNCTION__) insert into table failed: \(db.lastErrorMessage())") }}queue.close()