Status Update
Comments
yb...@google.com <yb...@google.com>
ya...@google.com <ya...@google.com>
ya...@google.com <ya...@google.com> #2
gm...@gmail.com <gm...@gmail.com> #3
Here's my entity:
@Entity(tableName = "palette")
class ManualPaletteEntity(
@PrimaryKey @ColumnInfo(name = "id") val id: String,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "time_millis") val timeMillis: Long,
)
@Entity(
tableName = "float_hsv",
foreignKeys = [
ForeignKey(
entity = ManualPaletteEntity::class,
parentColumns = ["id"],
childColumns = ["palette_id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class FloatHSVEntity(
@ColumnInfo(name = "hue") val hue: Float,
@ColumnInfo(name = "saturation") val saturation: Float,
@ColumnInfo(name = "value") val value: Float,
@ColumnInfo(name = "alpha") val alpha: Float,
@ColumnInfo(name = "palette_id") val paletteId: String,
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Int = 0,
)
ya...@google.com <ya...@google.com> #4
FK violation would happen based on the data in the database.
For that example, if you have anything in float_hsv
where palette_id
does not match an id
from ManuelPaletteEntity
, it would crash.
I'm also not sure sqlite is even able to detect that match after the fact, we should probably test that and figure out if we can workaround it.
gm...@gmail.com <gm...@gmail.com> #5
Alright, I'll try to figure out what's wrong
ya...@google.com <ya...@google.com> #6
Yep, you were right. There's a FK violation
ap...@google.com <ap...@google.com> #7
Thanks for checking it. @Elif, lets use this bug to see if we can improve the message.
We could even consider checking for FKey violations ourselves by generating a query and printing a better message. Though if that happens on production, that would mean repeatedly crashing the application :/.
That is probably the right thing to do. Room used to migrate destructively by default and developers didn't like it. We might also consider providing an API to delete violating entries in a future release.
Description
Version used: 2.0.0
Devices/Android versions reproduced on: Wileyfox Swift (API 25)
Not reproduced on Android Emulator API 15 (probably due to different SQLite version).
SQLite constraint violation on method annotated with @Insert(onConflict = OnConflictStrategy.ROLLBACK) causes SQLiteException instead of SQLiteConstraintException.
Stack trace example:
E/AndroidRuntime: FATAL EXCEPTION: Thread-8
Process: gmk57.roomtest, PID: 2152
android.database.sqlite.SQLiteException: cannot rollback - no transaction is active (code 1)
at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:555)
at android.database.sqlite.SQLiteSession.endTransactionUnchecked(SQLiteSession.java:439)
at android.database.sqlite.SQLiteSession.endTransaction(SQLiteSession.java:401)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:524)
at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.endTransaction(FrameworkSQLiteDatabase.java:90)
at androidx.room.RoomDatabase.endTransaction(RoomDatabase.java:266)
at gmk57.roomtest.DataDao_Impl.insertRollback(DataDao_Impl.java:99)
at gmk57.roomtest.MainActivity.violateRollback(MainActivity.java:67)
Taking into account that
1) Room wraps methods annotated with @Insert, @Update and @Transaction in explicit transaction, and
2) ABORT, FAIL and ROLLBACK all throw SQLiteConstraintException, effectively rolling back this transaction
- the broader question is: is there any reason to provide FAIL and ROLLBACK options at all?
I also think the documentation should clearly describe the behavior of each strategy in specific case of Android + Room (e.g. which strategies throw an exception and which do not), instead of just linking to partly irrelevant SQLite documentation.
Sample project attached.