Fixed
Status Update
Comments
an...@gmail.com <an...@gmail.com> #2
Project: platform/frameworks/support
Branch: androidx-master-dev
commit b90079595f33f58fece04026a97faa0d243acdb1
Author: Yuichi Araki <yaraki@google.com>
Date: Wed Sep 18 16:55:49 2019
Change the way to detect mismatch between POJO and query
This fixes cursor mismatch warnings with expandProjection.
Bug: 140759491
Test: QueryMethodProcessorTest
Change-Id: I7659002e5e0d1ef60fc1af2a625c0c36da0664d8
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
M room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
M room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
https://android-review.googlesource.com/1123258
https://goto.google.com/android-sha1/b90079595f33f58fece04026a97faa0d243acdb1
Branch: androidx-master-dev
commit b90079595f33f58fece04026a97faa0d243acdb1
Author: Yuichi Araki <yaraki@google.com>
Date: Wed Sep 18 16:55:49 2019
Change the way to detect mismatch between POJO and query
This fixes cursor mismatch warnings with expandProjection.
Bug: 140759491
Test: QueryMethodProcessorTest
Change-Id: I7659002e5e0d1ef60fc1af2a625c0c36da0664d8
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
M room/compiler/src/test/kotlin/androidx/room/processor/QueryMethodProcessorTest.kt
M room/compiler/src/test/kotlin/androidx/room/testing/TestProcessor.kt
yb...@google.com <yb...@google.com>
da...@google.com <da...@google.com> #3
an...@gmail.com <an...@gmail.com> #4
Project: platform/frameworks/support
Branch: androidx-master-dev
commit bdde5a1a970ddc9007b28de4aa29d60ffa588f08
Author: Yigit Boyar <yboyar@google.com>
Date: Thu Apr 16 16:47:05 2020
Re-factor how errors are dismissed when query is re-written
This CL changes how we handle errors/warnings if query is
re-written.
There was a bug in expandProjection where we would report warnings
for things that Room already fixes automatically ( b/140759491 ).
The solution to that problem (I7659002e5e0d1ef60fc1af2a625c0c36da0664d8)
solved it by deferring validating of columns until after re-write
decision is made. Unfortunately, this required changing PojoRowAdapter
to have a dummy mapping until it is validating, make it hard to use
as it does have a non-null mapping which is not useful.
This CL partially reverts that change and instead rely on the log
deferring logic we have in Context. This way, we don't need to break
the stability of PojoRowAdapter while still having the ability to
drop warnings that room fixes. This will also play nicer when we
have different query re-writing options that can use more information
about the query results.
Bug: 153387066
Bug: 140759491
Test: existing tests pass
Change-Id: I2ec967c763d33d7a3ff02c1a13c6953b460d1e5f
M room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
https://android-review.googlesource.com/1288456
Branch: androidx-master-dev
commit bdde5a1a970ddc9007b28de4aa29d60ffa588f08
Author: Yigit Boyar <yboyar@google.com>
Date: Thu Apr 16 16:47:05 2020
Re-factor how errors are dismissed when query is re-written
This CL changes how we handle errors/warnings if query is
re-written.
There was a bug in expandProjection where we would report warnings
for things that Room already fixes automatically (
The solution to that problem (I7659002e5e0d1ef60fc1af2a625c0c36da0664d8)
solved it by deferring validating of columns until after re-write
decision is made. Unfortunately, this required changing PojoRowAdapter
to have a dummy mapping until it is validating, make it hard to use
as it does have a non-null mapping which is not useful.
This CL partially reverts that change and instead rely on the log
deferring logic we have in Context. This way, we don't need to break
the stability of PojoRowAdapter while still having the ability to
drop warnings that room fixes. This will also play nicer when we
have different query re-writing options that can use more information
about the query results.
Bug: 153387066
Bug: 140759491
Test: existing tests pass
Change-Id: I2ec967c763d33d7a3ff02c1a13c6953b460d1e5f
M room/compiler/src/main/kotlin/androidx/room/log/RLog.kt
M room/compiler/src/main/kotlin/androidx/room/processor/QueryMethodProcessor.kt
M room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
M room/compiler/src/main/kotlin/androidx/room/solver/query/result/PojoRowAdapter.kt
da...@google.com <da...@google.com> #5
It seems sqlite-framework:2.0.1 never made it to maven.google.com , we'll release it soon along with Room 2.1.0-alpha05 which should correctly depend on it. Sorry for the inconvenience.
an...@gmail.com <an...@gmail.com> #6
Thanks! I will definitely try the newest room version.
However, more I look at the code, more I believe the problem is elsewhere. If the migration fails, there will be no `SQLiteDatabase` and no `getWrappedDb(db)`. According to the code of `SQLiteOpenHelper`, there should be only one query before migration. The list of queries should be:
PRAGMA user_version;
DROP TABLE IF EXISTS `tracking_events` <--- this fails due closed database
DROP TABLE IF EXISTS `items` <-- never happens
More findings caught by my eye:
- I tried to make sure all DAO queries happen on a single thread. No success.
- The crash happens on a small number of users, but users get many crashes. I am afraid the user is unable to launch the app.
- Most crashes come from Samsung devices. But `SQLiteOpenHelper` class were not changed. All lines of stacktrace matches.
- `SQLiteOpenHelper` was constructed only once for `vinted_database.db`. However, meminfo shows something I don't understand:
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 512 61 104/135/8 /data/user/0/lt.ito.md/databases/vinted_database.db
4 8 0/0/0 (attached) temp
4 512 25 35/14/2 /data/user/0/lt.ito.md/databases/vinted_database.db (3)
Looks like database was opened two times. There was opened more databases in my app, but no one appears in this list.
What else I could check?
However, more I look at the code, more I believe the problem is elsewhere. If the migration fails, there will be no `SQLiteDatabase` and no `getWrappedDb(db)`. According to the code of `SQLiteOpenHelper`, there should be only one query before migration. The list of queries should be:
PRAGMA user_version;
DROP TABLE IF EXISTS `tracking_events` <--- this fails due closed database
DROP TABLE IF EXISTS `items` <-- never happens
More findings caught by my eye:
- I tried to make sure all DAO queries happen on a single thread. No success.
- The crash happens on a small number of users, but users get many crashes. I am afraid the user is unable to launch the app.
- Most crashes come from Samsung devices. But `SQLiteOpenHelper` class were not changed. All lines of stacktrace matches.
- `SQLiteOpenHelper` was constructed only once for `vinted_database.db`. However, meminfo shows something I don't understand:
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 512 61 104/135/8 /data/user/0/
4 8 0/0/0 (attached) temp
4 512 25 35/14/2 /data/user/0/
Looks like database was opened two times. There was opened more databases in my app, but no one appears in this list.
What else I could check?
da...@google.com <da...@google.com> #7
This type of behavior can also be seen when the corrupted database recovery mechanism is not correctly performed. Something that sqlite-framework:2.0.1 also fixed over its previous version.
See this patch and specifically the test in it:https://android.googlesource.com/platform/frameworks/support/+/611c90a4711670f8fe0d66ff2eaa8cb0266422d5
When the DB is corrupted (outside your control, and very little to do really) then the DB is immediately closed in hopes of creating a new DB (and a new object). What ends up happening is the corrupted object is still used causing the first db operation to fail (in this case a migration or that DROP TABLE IF EXISTS).
See this patch and specifically the test in it:
When the DB is corrupted (outside your control, and very little to do really) then the DB is immediately closed in hopes of creating a new DB (and a new object). What ends up happening is the corrupted object is still used causing the first db operation to fail (in this case a migration or that DROP TABLE IF EXISTS).
an...@gmail.com <an...@gmail.com> #8
That makes sense. I will update the app as soon as the new Room will be released and let you know if it helps.
Description
Version used: 2.1.0-alpha03
Devices/Android versions reproduced on: All devices. minSdk = 21. Most devices are Samsung (~90%)
I am getting tons of crashes and I am not able to reproduce them. Please see to attached stacktrace. I am using a default migration (drop everything -> recreate everything):
@Provides
@PerApplicationScope
fun provideDatabase(application: Application): VintedDatabase {
val builder = Room.databaseBuilder(
application,
VintedDatabase::class.java,
"vinted_database.db"
)
.fallbackToDestructiveMigration()
if (Debug.isDebuggerConnected()) {
builder.allowMainThreadQueries()
}
return builder.build()
}
The application is crashing on random DAO calls in various places in the app. There is a similar issue:
This generated code looks very stable. Also, everything at FrameworkSQLiteOpenHelper is synchronized, and I don't get how is possible to close DB during migration. But one thing caught my eye there:
FrameworkSQLiteDatabase getWrappedDb(SQLiteDatabase sqLiteDatabase) {
FrameworkSQLiteDatabase dbRef = mDbRef[0];
if (dbRef == null) {
dbRef = new FrameworkSQLiteDatabase(sqLiteDatabase);
mDbRef[0] = dbRef;
}
return mDbRef[0];
}
Just hypothetically, what if someone gets a DB through `FrameworkSQLiteOpenHelper.getWritableDatabase()` and closes immediate, like:
FrameworkSQLiteOpenHelper.getWritableDatabase().close()
Then DB instance will be closed and opening a new writable database gives a new SQLiteDatabase instance. But getWrappedDb returns an old one because the ref was not cleared because DB was closed directly instead of FrameworkSQLiteOpenHelper. Maybe some safety is needed here, like:
if (dbRef != null && dbRef.mDelegate != sqLiteDatabase) {
//try to close old instance anyway to avoid memory leak
dbRef.close()
dbRef = null
}
//rest code
Need to mention, DAO requests could be done on a few IO threads. Maybe Single thread environment would be better?