Before reading the documentation, I would have expected SQLiteDatabase's insertOrThrow()
method to have thrown an exception if the insert wasn't successful.
However, the documentation says that the insertOrThrow()
method
returns the row ID of the newly inserted row, or -1 if an error occurred
So, if it returns -1
when an error occurs, under what circumstances does it throw an exception?
My understanding is that it will return -1 if all the code could be executed properly and a "EXPECTED" error happened. However, not all errors/exceptions are handled and some exceptions may still be triggered:
HERE you can find the implementation of insert()
and insertOrThrow()
.
You can see that both methods are similar. However, insert()
handles SQLException
s for you. insertOrThrow()
does not handle any exception and you should do it by yourself.
public long insert(String table, String nullColumnHack, ContentValues values) {
try {
return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
} catch (SQLException e) {
Log.e(TAG, "Error inserting " + values, e);
return -1;
}
}
public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
throws SQLException {
return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE);
}
Both methods calls insertWithOnConflict()
which implementation is HERE:
public long insertWithOnConflict(String table, String nullColumnHack,
ContentValues initialValues, int conflictAlgorithm) {
acquireReference();
try {
// CODE
try {
// ONLY HERE I return some value.... Otherwise, I'll raise an exception
return statement.executeInsert();
} finally {
statement.close();
}
} finally {
releaseReference();
}
}
In the implementation, you will see that it returns "-1" only if statement.executeInsert();
returns something (and it seems that "-1" came from here):
.../frameworks/base/core/jni/android_database_SQLiteConnection.cpp
static jlong nativeExecuteForLastInsertedRowId(JNIEnv* env, jclass clazz,
jlong connectionPtr, jlong statementPtr) {
SQLiteConnection* connection = reinterpret_cast<SQLiteConnection*>(connectionPtr);
sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr);
int err = executeNonQuery(env, connection, statement);
return err == SQLITE_DONE && sqlite3_changes(connection->db) > 0
? sqlite3_last_insert_rowid(connection->db) : -1;
}
If any other error/exception happens in the middle, it will throws an exception.
If you follows the called methods, you can see that other errors are not handled. Also, you will notice that the SQLite will be in fact be executed by a C task (and not java). So, several non-expected errors can still happen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With