public @interface

ForeignKey

implements java.lang.annotation.Annotation

 androidx.room.ForeignKey

Overview

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 ForeignKey.deferred() to true. You can also use defer_foreign_keys PRAGMA to defer them depending on your transaction.

Please refer to the SQLite foreign keys documentation for details.

Summary

Fields
public static final intCASCADE

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

public static final intNO_ACTION

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

public static final intRESTRICT

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

public static final intSET_DEFAULT

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

public static final intSET_NULL

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

Fields

public static final int NO_ACTION

Possible value for ForeignKey.onDelete() or ForeignKey.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.

public static final int RESTRICT

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

The RESTRICT action means that the application is prohibited from deleting (for ForeignKey.onDelete()) or modifying (for ForeignKey.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 ForeignKey.deferred() constraint.

Even if the foreign key constraint it is attached to is ForeignKey.deferred(), configuring a RESTRICT action causes SQLite to return an error immediately if a parent key with dependent child keys is deleted or modified.

public static final int SET_NULL

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

If the configured action is "SET NULL", then when a parent key is deleted (for ForeignKey.onDelete()) or modified (for ForeignKey.onUpdate()), the child key columns of all rows in the child table that mapped to the parent key are set to contain NULL values.

public static final int SET_DEFAULT

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

The "SET DEFAULT" actions are similar to ForeignKey.SET_NULL, except that each of the child key columns is set to contain the columns default value instead of NULL.

public static final int CASCADE

Possible value for ForeignKey.onDelete() or ForeignKey.onUpdate().

A "CASCADE" action propagates the delete or update operation on the parent key to each dependent child key. For ForeignKey.onDelete() action, this means that each row in the child entity that was associated with the deleted parent row is also deleted. For an ForeignKey.onUpdate() action, it means that the values stored in each dependent child key are modified to match the new parent key values.

Source

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.room;

import androidx.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Declares a foreign key on another {@link Entity}.
 * <p>
 * Foreign keys allows you to specify constraints across Entities such that SQLite will ensure that
 * the relationship is valid when you modify the database.
 * <p>
 * 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).
 * <p>
 * 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
 * {@link RoomWarnings#MISSING_INDEX_ON_FOREIGN_KEY_CHILD} warning.
 * <p>
 * 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 {@link #deferred()} to
 * {@code true}. You can also use
 * <a href="https://sqlite.org/pragma.html#pragma_defer_foreign_keys">defer_foreign_keys</a> PRAGMA
 * to defer them depending on your transaction.
 * <p>
 * Please refer to the SQLite <a href="https://sqlite.org/foreignkeys.html">foreign keys</a>
 * documentation for details.
 */
@Target({})
@Retention(RetentionPolicy.CLASS)
public @interface ForeignKey {
    /**
     * The parent Entity to reference. It must be a class annotated with {@link Entity} and
     * referenced in the same database.
     *
     * @return The parent Entity.
     */
    Class<?> entity();

    /**
     * The list of column names in the parent {@link Entity}.
     * <p>
     * Number of columns must match the number of columns specified in {@link #childColumns()}.
     *
     * @return The list of column names in the parent Entity.
     * @see #childColumns()
     */
    String[] parentColumns();

    /**
     * The list of column names in the current {@link Entity}.
     * <p>
     * Number of columns must match the number of columns specified in {@link #parentColumns()}.
     *
     * @return The list of column names in the current Entity.
     */
    String[] childColumns();

    /**
     * Action to take when the parent {@link Entity} is deleted from the database.
     * <p>
     * By default, {@link #NO_ACTION} is used.
     *
     * @return The action to take when the referenced entity is deleted from the database.
     */
    @Action int onDelete() default NO_ACTION;

    /**
     * Action to take when the parent {@link Entity} is updated in the database.
     * <p>
     * By default, {@link #NO_ACTION} is used.
     *
     * @return The action to take when the referenced entity is updated in the database.
     */
    @Action int onUpdate() default 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 {@code true}.
     * You can also use
     * <a href="https://sqlite.org/pragma.html#pragma_defer_foreign_keys">defer_foreign_keys</a>
     * PRAGMA to defer them depending on your transaction.
     *
     * @return Whether the foreign key constraint should be deferred until the transaction is
     * complete. Defaults to {@code false}.
     */
    boolean deferred() default false;

    /**
     * Possible value for {@link #onDelete()} or {@link #onUpdate()}.
     * <p>
     * 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.
     */
    int NO_ACTION = 1;

    /**
     * Possible value for {@link #onDelete()} or {@link #onUpdate()}.
     * <p>
     * The RESTRICT action means that the application is prohibited from deleting
     * (for {@link #onDelete()}) or modifying (for {@link #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
     * {@link #deferred()} constraint.
     * <p>
     * Even if the foreign key constraint it is attached to is {@link #deferred()}, configuring a
     * RESTRICT action causes SQLite to return an error immediately if a parent key with dependent
     * child keys is deleted or modified.
     */
    int RESTRICT = 2;

    /**
     * Possible value for {@link #onDelete()} or {@link #onUpdate()}.
     * <p>
     * If the configured action is "SET NULL", then when a parent key is deleted
     * (for {@link #onDelete()}) or modified (for {@link #onUpdate()}), the child key columns of all
     * rows in the child table that mapped to the parent key are set to contain {@code NULL} values.
     */
    int SET_NULL = 3;

    /**
     * Possible value for {@link #onDelete()} or {@link #onUpdate()}.
     * <p>
     * The "SET DEFAULT" actions are similar to {@link #SET_NULL}, except that each of the child key
     * columns is set to contain the columns default value instead of {@code NULL}.
     */
    int SET_DEFAULT = 4;

    /**
     * Possible value for {@link #onDelete()} or {@link #onUpdate()}.
     * <p>
     * A "CASCADE" action propagates the delete or update operation on the parent key to each
     * dependent child key. For {@link #onDelete()} action, this means that each row in the child
     * entity that was associated with the deleted parent row is also deleted. For an
     * {@link #onUpdate()} action, it means that the values stored in each dependent child key are
     * modified to match the new parent key values.
     */
    int CASCADE = 5;

    /**
     * Constants definition for values that can be used in {@link #onDelete()} and
     * {@link #onUpdate()}.
     */
    @IntDef({NO_ACTION, RESTRICT, SET_NULL, SET_DEFAULT, CASCADE})
    @Retention(RetentionPolicy.CLASS)
    @interface Action {
    }
}