Status Update
Comments
ap...@google.com <ap...@google.com> #2
So, the view is something we added recently. It appears that
- removing the view entirely, the destructive migration works. But it doesn't actually remove the view.
- adding the view back in, the destructive migration fails with the same message.
It appears that the destructive migration is not dropping the view, but it does try to create it again, which is what blows up.
I was able to work around this by adding a RoomCallback
and overriding the onDestructiveMigration callback to manually delete the view:
override fun onDestructiveMigration(connection: SQLiteConnection) {
super.onDestructiveMigration(connection)
connection.execSQL("DROP VIEW IF EXISTS calendar_items_view")
}
This is a pretty big potential footgun for anyone using views with destructive migrations!
ap...@google.com <ap...@google.com> #3
This sounds like a bug, with destructive migrations turned ON, views should also be recreated and it seems they are not being dropped before being created again leading to the 'already exists' issue.
na...@google.com <na...@google.com> #4
Project: platform/frameworks/support
Branch: androidx-main
Author: Daniel Santiago Rivera <
Link:
Drop views during destructive migrations.
Expand for full commit details
Drop views during destructive migrations.
When 'allowDestructiveMigrationForAllTables' is turned ON (default in KMP) it should also drop all views so they can be recreated, this follows the same behaviour as when 'allowDestructiveMigrationForAllTables' is OFF and the RoomDatabase defined views are dropped.
Bug: 381518941
Test: MigrationTest
Change-Id: Iaf27b30b859b3a21f71d252e5c223dfd28365da0
Files:
- M
room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/migration/MigrationTest.java
- M
room/room-runtime/src/androidMain/kotlin/androidx/room/RoomOpenHelper.android.kt
- M
room/room-runtime/src/commonMain/kotlin/androidx/room/RoomConnectionManager.kt
Hash: 0a3e83009a1f514c7d43870110b63eebb0371efc
Date: Wed Dec 04 10:53:59 2024
Description
Some more details in b/388353336
Start of trace:
This happens because when we draw we use a shared ContentDrawScope implementation that we render all DrawModifierNodes in. We do this by mutating a property as we draw successive nodes. However, this means that if anyone captures a reference to this draw scope and tries to draw it later on, this will cause a NPE error as we don't know what the 'current node' that needs to be drawn in.
For the general case this is an error and scopes shouldn't be captured and stored outside the scope in this way, but for GraphicsLayer this is needed when recording drawContent to support some edge cases, such as when we need to draw a layer implementation that can't be drawn in software, within software rendering (such as drawing to a Bitmap). For this we just end up re-invoking the draw block we captured.
We considered some solutions where we would allocate a new draw scope instance per modifier, but this adds some overhead and 'storing' these draw scopes for future use is challenging. (we considered putting them on the node object, in a map on the node coordinator, or some other chain structure on the node coordinator, but none of these are really great)
Instead we can explicitly support the GraphicsLayer.record case by overriding the DrawScope#GraphicsLayer.record function and making it handle this case properly. This can still cause issues if using the non-DrawScope scoped record function, but developers should move to the DrawScope one instead.