Closed WonShaw closed 2 years ago
There are other SELECT CHANGES
usages in ormlite-android, I have no plan to modify them for now. Sorry.
Wow, thanks for this @WonShaw . I assume that the executeUpdateDelete()
method was added more recently. What version of the Android OS started the support for it?
executeUpdateDelete()
was added in api level 11 (Android 3.0.x honeycomb)
Since android add setWriteAheadLoggingEnabled
in api level 16, and the db connection poll size was restricted to 1 when using rollback journal, so it's ok to use the original implementation below api level 11.
I have changed my commit.
For the record, I refactored this code a bit. See: https://github.com/j256/ormlite-android/commit/d9cf9cab3f76fa4335f0380a259712fae8420d55
There is a bug in
AndroidDatabaseConnection.update
.AndroidDatabaseConnection.update
execute the update sql first, then executeSELECT CHANGES()
to get the changed row number.The update procedure is as follows:
SELECT CHANGES()
However, it only works when update sql and
SELECT CHANGES()
are executed on same SQLiteConnection, in other words: connection A and connection B must be the same connection.These code works fine before, because Android restricts sqlite connection pool size to 1 by defaullt. (see this).
Or more precisely, Android sqlite connection pool size == 1 when the journal mode of sqlite database is rollback journal.
If the connection pool size == 1, obviously, connection A == connection B.
However, when developer enable WAL mode of sqlite by calling setWriteAheadLoggingEnabled, the connection pool size will be 4 instead of 1.
Besides, Android introduced
primary connection
andnon primary connection
, if WAL mode is enabled, there will be only 1primary connection
that can write the sqlite database, and 3non primary connection
that can only read the sqlite. When execute readOnly sql,non primary connection
will be used first, if allnon primary connection
s are not available, will try acquireprimary connection
. When execute readWrite sql, onlyprimary connection
can be used.So, look back to update procedure:
SELECT CHANGES()
Step.1 must acquire the
primary connection
then execute update sql in Step.2.Step.3 will acquire one of the
non primary connection
in most cases, which is not the same connection as theprimary connection
Step.4 always get
0
if the connection in Step.3 is different from the connection in Step.2. (Almost certainly)So we must change
update
to useexecuteUpdateDelete
directly, it will execute sqlite3_changes internally and return the changed row number.