Fixed
Status Update
Comments
ia...@gmail.com <ia...@gmail.com> #2
I'm still working on a fix, but here's the current state of OnConflictStrategy.
# REPLACE
Works as expected. Old rows are replaced.
# IGNORE
Works as expected. New rows are ignored.
# ROLLBACK
This ends the transaction on conflict. Thus, the following call of endTransaction() always fails. This is basically unusable.
# ABORT (default)
As the SQLite doc says, all the changes prior to this statement are preserved, but they are rolled back by the surrounding transaction anyway.
# FAIL
This works pretty much the same as ABORT, except that it does not roll back the current statement at first. It is, however, rolled back by the surrounding transaction along with the preceding changes.
In summary, ABORT and FAIL produce the same results, and unlike the SQLite doc says, they both roll back on conflict (because of the surrounding transaction). ROLLBACK always fails.
# REPLACE
Works as expected. Old rows are replaced.
# IGNORE
Works as expected. New rows are ignored.
# ROLLBACK
This ends the transaction on conflict. Thus, the following call of endTransaction() always fails. This is basically unusable.
# ABORT (default)
As the SQLite doc says, all the changes prior to this statement are preserved, but they are rolled back by the surrounding transaction anyway.
# FAIL
This works pretty much the same as ABORT, except that it does not roll back the current statement at first. It is, however, rolled back by the surrounding transaction along with the preceding changes.
In summary, ABORT and FAIL produce the same results, and unlike the SQLite doc says, they both roll back on conflict (because of the surrounding transaction). ROLLBACK always fails.
yb...@google.com <yb...@google.com>
yb...@google.com <yb...@google.com> #3
Yes, this is exactly what I observed. It seems that FAIL and ROLLBACK strategies don't make much sense for Room. If this is correct, maybe you should deprecate and later remove them to avoid confusion?
ia...@gmail.com <ia...@gmail.com> #5
Fine!
Maybe it would also be useful to mention in the docs which strategies can throw an SQLiteConstraintException (btw, is it the only possible type of exception?) and which cannot.
Maybe it would also be useful to mention in the docs which strategies can throw an SQLiteConstraintException (btw, is it the only possible type of exception?) and which cannot.
yb...@google.com <yb...@google.com> #6
SQLiteConstraintException is the only type thrown by the platform SQLite, but if you use custom implementation [1], it might throw something else.
[1]:https://developer.android.com/reference/android/arch/persistence/room/RoomDatabase.Builder.html#openHelperFactory(android.arch.persistence.db.SupportSQLiteOpenHelper.Factory)
[1]:
ap...@google.com <ap...@google.com> #7
Project: platform/frameworks/support
Branch: androidx-master-dev
commit b8b669fd8cc863ad19a5e6c912b163aab107a86f
Author: Yuichi Araki <yaraki@google.com>
Date: Mon Dec 03 11:40:46 2018
Deprecate OnConflictStrategy.ROLLBACK and FAIL
OnConflictStrategy.ROLLBACK was never working properly. On conflict, it
always fails with SQLiteException since Room tries to end the
transaction which has already been rolled back by the conflict. In
addition, framework has a bug in handling of transaction around ROLLBACK
( b/120397728 ), so it is impossible to make this work as expected.
Instead, ABORT has always worked like ROLLBACK. This is because the
INSERT throws SQLiteConstraintException on conflict, so the wrapping
transaction is ended without being marked as successful and thus rolled
back. We could change this to work more like SQLite's original ABORT
(keep preceding changes in the transaction), but it is too risky to
change the behavior of ABORT since it is the default option of @Insert
and @Update. This CL just clarifies the behavior in Javadoc.
OnConflictStrategy.FAIL is no different from ABORT because of the
wrapping transaction. We should just remove it for clarity.
REPLACE and IGNORE are working fine.
Bug: 117266738
Test: OnConflictStrategyTest
Change-Id: Id62920d531afe4644d9d37ffc823a65132b54b4f
M room/common/api/2.1.0-alpha03.txt
M room/common/api/current.txt
M room/common/src/main/java/androidx/room/Insert.java
M room/common/src/main/java/androidx/room/OnConflictStrategy.java
M room/common/src/main/java/androidx/room/Update.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/OnConflictStrategyTest.java
https://android-review.googlesource.com/839274
https://goto.google.com/android-sha1/b8b669fd8cc863ad19a5e6c912b163aab107a86f
Branch: androidx-master-dev
commit b8b669fd8cc863ad19a5e6c912b163aab107a86f
Author: Yuichi Araki <yaraki@google.com>
Date: Mon Dec 03 11:40:46 2018
Deprecate OnConflictStrategy.ROLLBACK and FAIL
OnConflictStrategy.ROLLBACK was never working properly. On conflict, it
always fails with SQLiteException since Room tries to end the
transaction which has already been rolled back by the conflict. In
addition, framework has a bug in handling of transaction around ROLLBACK
(
Instead, ABORT has always worked like ROLLBACK. This is because the
INSERT throws SQLiteConstraintException on conflict, so the wrapping
transaction is ended without being marked as successful and thus rolled
back. We could change this to work more like SQLite's original ABORT
(keep preceding changes in the transaction), but it is too risky to
change the behavior of ABORT since it is the default option of @Insert
and @Update. This CL just clarifies the behavior in Javadoc.
OnConflictStrategy.FAIL is no different from ABORT because of the
wrapping transaction. We should just remove it for clarity.
REPLACE and IGNORE are working fine.
Bug: 117266738
Test: OnConflictStrategyTest
Change-Id: Id62920d531afe4644d9d37ffc823a65132b54b4f
M room/common/api/2.1.0-alpha03.txt
M room/common/api/current.txt
M room/common/src/main/java/androidx/room/Insert.java
M room/common/src/main/java/androidx/room/OnConflictStrategy.java
M room/common/src/main/java/androidx/room/Update.java
A room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/OnConflictStrategyTest.java
ap...@google.com <ap...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-master-dev
commit f0f9ed8db13fbeb028391af00b626e19a0f2746e
Author: Daniel Santiago Rivera <danysantiago@google.com>
Date: Mon Feb 11 14:35:55 2019
Deprecate RoomDatabase transaction methods.
Deprecate beginTransaction, setTransactionSuccessful and endTransaction,
in favor of runInTransaction. Deprecating these methods discourage
users from using them within coroutines.
Bug: 120854786
Test: ./gradlew room:room-compiler:test
room:integration-tests:room-testapp-kotlin:cC
room:integration-tests:room-testapp:cC
Change-Id: Idc1bb04555fdba78eb1142b3ba461b87e6b06a69
M room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
M room/compiler/src/test/data/daoWriter/output/DeletionDao.java
M room/compiler/src/test/data/daoWriter/output/UpdateDao.java
M room/compiler/src/test/data/daoWriter/output/WriterDao.java
M room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
M room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
M room/coroutines/src/main/java/androidx/room/RoomDatabase.kt
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/FtsMigrationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ForeignKeyTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/WriteAheadLoggingTest.java
M room/runtime/api/2.1.0-alpha05.txt
M room/runtime/api/current.txt
M room/runtime/src/main/java/androidx/room/RoomDatabase.java
M room/runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.java
https://android-review.googlesource.com/900916
https://goto.google.com/android-sha1/f0f9ed8db13fbeb028391af00b626e19a0f2746e
Branch: androidx-master-dev
commit f0f9ed8db13fbeb028391af00b626e19a0f2746e
Author: Daniel Santiago Rivera <danysantiago@google.com>
Date: Mon Feb 11 14:35:55 2019
Deprecate RoomDatabase transaction methods.
Deprecate beginTransaction, setTransactionSuccessful and endTransaction,
in favor of runInTransaction. Deprecating these methods discourage
users from using them within coroutines.
Bug: 120854786
Test: ./gradlew room:room-compiler:test
room:integration-tests:room-testapp-kotlin:cC
room:integration-tests:room-testapp:cC
Change-Id: Idc1bb04555fdba78eb1142b3ba461b87e6b06a69
M room/compiler/src/main/kotlin/androidx/room/writer/ClassWriter.kt
M room/compiler/src/test/data/daoWriter/output/ComplexDao.java
M room/compiler/src/test/data/daoWriter/output/DeletionDao.java
M room/compiler/src/test/data/daoWriter/output/UpdateDao.java
M room/compiler/src/test/data/daoWriter/output/WriterDao.java
M room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
M room/compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
M room/coroutines/src/main/java/androidx/room/RoomDatabase.kt
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/migration/MigrationKotlinTest.kt
M room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/FtsMigrationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/paging/DataSourceFactoryTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ForeignKeyTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/QueryTransactionTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/WriteAheadLoggingTest.java
M room/runtime/api/2.1.0-alpha05.txt
M room/runtime/api/current.txt
M room/runtime/src/main/java/androidx/room/RoomDatabase.java
M room/runtime/src/main/java/androidx/room/paging/LimitOffsetDataSource.java
Description
withContext(Dispatchers.Default) {
db.beginTransaction()
db.insert(data) // DAO suspend function
db.update(anotherData) // DAO suspend function
db.setTransactionSuccessful()
db.endTransaction()
}
This can deadlock because transaction are exclusive and are ThreadLocal, meaning once a transaction is started in a thread form the default dispatcher, another coroutine dispatcher thread will get blocked even if we are within the same coroutine.