Android - When does insertOrThrow() throw an exception?
Asked Answered
M

3

7

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?

Maramarabel answered 6/7, 2016 at 13:50 Comment(1)
When errors occurs, such as IO errors, wrong data set, closed Cursor writte, non-writte privileges writte attempt, etc. Mostly if any error happens, -1 (the no row was affected) information is givenIntuitional
L
4

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:

  • SQLiteDatabaseCorruptException
  • IllegalArgumentException
  • RuntimeException
  • Database is opened for read-only
  • Trying to insert a duplicated key

HERE you can find the implementation of insert() and insertOrThrow().

You can see that both methods are similar. However, insert() handles SQLExceptions 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.

Leaves answered 6/7, 2016 at 14:49 Comment(1)
This still does not answer when exactly -1 is returned. executeNonQuery always returns SQLITE_DONE.Cheeseburger
M
0

You can look up the SQLiteDatabase source code to see how it works. It seems it will throw a SQLiteDatabaseCorruptException if the SQL string is invalid, otherwise return -1.

Mcclish answered 6/7, 2016 at 14:4 Comment(3)
Can you explain? The link in my post shows the method he's asking about, which throws an SQLiteDatabaseException on an executeInsert call.Mcclish
The throws clause specifies what exceptions the function can throw. There is no throw statement in the code you've linked to.Cheeseburger
executeInsert throws an exception. Though insertWithOnConflict() does not declare that it throws it it is caught by insertOrThrow().Mcclish
P
-1

The insertOrThrow() method throws the exception and returns -1. In this way you can check if your query was sucesful nor not. If it return a -1 your action was not completed and you need to figure out what went wrong!

Passive answered 6/7, 2016 at 13:59 Comment(1)
It can't return -1 and throw an exception at the same time. So my question is when does it return -1 and when does it throw an exception.Maramarabel

© 2022 - 2024 — McMap. All rights reserved.