package androidx.room import androidx.annotation.IntDef import kotlin.reflect.KClass /** * Declares a foreign key on another [Entity]. * * * Foreign keys allows you to specify constraints across Entities such that SQLite will ensure that * the relationship is valid when you modify the database. * * * When a foreign key constraint is specified, SQLite requires the referenced columns to be part of * a unique index in the parent table or the primary key of that table. You must create a unique * index in the parent entity that covers the referenced columns (Room will verify this at compile * time and print an error if it is missing). * * * It is also recommended to create an index on the child table to avoid full table scans when the * parent table is modified. If a suitable index on the child table is missing, Room will print * [RoomWarnings.MISSING_INDEX_ON_FOREIGN_KEY_CHILD] warning. * * * A foreign key constraint can be deferred until the transaction is complete. This is useful if * you are doing bulk inserts into the database in a single transaction. By default, foreign key * constraints are immediate but you can change this value by setting [.deferred] to * `true`. You can also use * [defer_foreign_keys](https://sqlite.org/pragma.html#pragma_defer_foreign_keys) PRAGMA * to defer them depending on your transaction. * * * Please refer to the SQLite [foreign keys](https://sqlite.org/foreignkeys.html) * documentation for details. */ annotation class ForeignKey( /** * The parent Entity to reference. It must be a class annotated with [Entity] and * referenced in the same database. * * @return The parent Entity. */ val entity: KClass<*>, /** * The list of column names in the parent [Entity]. * * * Number of columns must match the number of columns specified in [.childColumns]. * * @return The list of column names in the parent Entity. * @see .childColumns */ val parentColumns: Array, /** * The list of column names in the current [Entity]. * * * Number of columns must match the number of columns specified in [.parentColumns]. * * @return The list of column names in the current Entity. */ val childColumns: Array, /** * Action to take when the parent [Entity] is deleted from the database. * * * By default, [.NO_ACTION] is used. * * @return The action to take when the referenced entity is deleted from the database. */ @Action val onDelete: Int = NO_ACTION, /** * Action to take when the parent [Entity] is updated in the database. * * * By default, [.NO_ACTION] is used. * * @return The action to take when the referenced entity is updated in the database. */ @Action val onUpdate: Int = NO_ACTION, /** * * A foreign key constraint can be deferred until the transaction is complete. This is useful * if you are doing bulk inserts into the database in a single transaction. By default, foreign * key constraints are immediate but you can change it by setting this field to `true`. * You can also use * [defer_foreign_keys](https://sqlite.org/pragma.html#pragma_defer_foreign_keys) * PRAGMA to defer them depending on your transaction. * * @return Whether the foreign key constraint should be deferred until the transaction is * complete. Defaults to `false`. */ val deferred: Boolean = false) { /** * Constants definition for values that can be used in [.onDelete] and * [.onUpdate]. */ @IntDef(NO_ACTION, RESTRICT, SET_NULL, SET_DEFAULT, CASCADE) @Retention(AnnotationRetention.SOURCE) annotation class Action companion object { /** * Possible value for [.onDelete] or [.onUpdate]. * * * When a parent key is modified or deleted from the database, no special action is taken. * This means that SQLite will not make any effort to fix the constraint failure, instead, * reject the change. */ const val NO_ACTION = 1 /** * Possible value for [.onDelete] or [.onUpdate]. * * * The RESTRICT action means that the application is prohibited from deleting * (for [.onDelete]) or modifying (for [.onUpdate]) a parent key when there * exists one or more child keys mapped to it. The difference between the effect of a RESTRICT * action and normal foreign key constraint enforcement is that the RESTRICT action processing * happens as soon as the field is updated - not at the end of the current statement as it would * with an immediate constraint, or at the end of the current transaction as it would with a * [.deferred] constraint. * * * Even if the foreign key constraint it is attached to is [.deferred], configuring a * RESTRICT action causes SQLite to return an error immediately if a parent key with dependent * child keys is deleted or modified. */ const val RESTRICT = 2 /** * Possible value for [.onDelete] or [.onUpdate]. * * * If the configured action is "SET NULL", then when a parent key is deleted * (for [.onDelete]) or modified (for [.onUpdate]), the child key columns of all * rows in the child table that mapped to the parent key are set to contain `NULL` values. */ const val SET_NULL = 3 /** * Possible value for [.onDelete] or [.onUpdate]. * * * The "SET DEFAULT" actions are similar to [.SET_NULL], except that each of the child key * columns is set to contain the columns default value instead of `NULL`. */ const val SET_DEFAULT = 4 /** * Possible value for [.onDelete] or [.onUpdate]. * * * A "CASCADE" action propagates the delete or update operation on the parent key to each * dependent child key. For [.onDelete] action, this means that each row in the child * entity that was associated with the deleted parent row is also deleted. For an * [.onUpdate] action, it means that the values stored in each dependent child key are * modified to match the new parent key values. */ const val CASCADE = 5 } }