![]() |
MySQL 9.7.0
Source Code Documentation
|
#include "sql/sql_foreign_key_constraint.h"#include <set>#include "scope_guard.h"#include "sql/dd/dd.h"#include "sql/dd/dd_table.h"#include "sql/dd/dictionary.h"#include "sql/dd/types/foreign_key.h"#include "sql/dd/types/foreign_key_element.h"#include "sql/field.h"#include "sql/histograms/table_histograms.h"#include "sql/key.h"#include "sql/mysqld.h"#include "sql/sql_base.h"#include "sql/sql_class.h"#include "sql/table.h"#include "sql/table_trigger_dispatcher.h"#include "sql/trigger_chain.h"Classes | |
| class | Foreign_key_chain |
| Class to store all foreign key names during CASCADE. More... | |
| class | No_fk_checks_guard |
| Helper to temporarily enable OPTION_NO_FOREIGN_KEY_CHECKS within a scope and restore the thread option bits during exit. More... | |
Functions | |
| static bool | check_all_child_fk_ref (THD *thd, const TABLE *table_p, enum_fk_dml_type dml_type, Foreign_key_chain *chain) |
| Check all foreign key constraints on child tables for DML operation on a parent table. More... | |
| static std::string | build_fk_error_message (THD *thd, bool check_child_access, bool check_parent_access, const TABLE *tbl, TABLE_SHARE_FOREIGN_KEY_INFO *fk) |
| Helper function to prepare error message. More... | |
| static bool | report_row_referenced_error (THD *thd, const TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk) |
| Reports ER_ROW_IS_REFERENCED_2 error with fk information. More... | |
| static bool | report_no_referenced_row_error (THD *thd, const TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk) |
| Reports ER_NO_REFERENCED_ROW_2 error with fk information. More... | |
| static TABLE * | find_fk_table_from_open_tables (THD *thd, const char *db_name, const char *table_name, const char *fk_name) |
| Find TABLE instance of a foreign key table from the THD::open_tables list. More... | |
| static uint | get_key_index (const TABLE *table, uint num_columns, LEX_CSTRING *col_names) |
| Function to get index of key matching col_names in keys list. More... | |
| static bool | is_column_updated (const TABLE *table, uint num_key_cols, LEX_CSTRING *col_names) |
| Function to check if any of the foreign key columns updated. More... | |
| static bool | is_self_fk_value_same (const TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk) |
| Function to check value of foreign key columns and parent columns are same in case self referencing foreign key. More... | |
| static bool | check_and_acquire_MDL_lock (THD *thd, const char *db_name, const char *table_name, enum_mdl_type mdl_type) |
| Check if MDL lock is already acquired on the table. More... | |
| static TABLE * | open_table_for_fk (THD *thd, const char *db_name, const char *table_name) |
| Function to open table for foreign key validation. More... | |
| static bool | is_fk_cascade (TABLE *table, enum_fk_dml_type dml_type, const char *fk_name) |
| Function to check if CASCADE action is defined for a foreign key on UPDATE or DELETE operations. More... | |
| static void | set_query_id (THD *thd, TABLE *table) |
| In stored functions/triggers, sub-statements follow the open-table call flow, so query_id ends up being set on the unused TABLE instance. More... | |
| static bool | get_foreign_key_table (THD *thd, const char *db_name, const char *table_name, const char *fk_name, enum_fk_dml_type dml_type, bool open_table, TABLE **table, bool *table_exists, bool *is_table_opened) |
| Function to get TABLE instance of a other table in FK relationship. More... | |
| static bool | set_updated_key_value (THD *thd, TABLE *table_c, int child_key_idx, const TABLE *table_p, int parent_key_idx, TABLE_SHARE_FOREIGN_KEY_INFO *fk) |
| Function to copy value to child table columns during UPDATE CASCADE operation. More... | |
| static bool | set_key_value_null (TABLE *table, uint num_key_cols, LEX_CSTRING *col_names) |
| Function to set the null value for key columns. More... | |
| bool | is_cascade_from_parent_legal (const TABLE *table_p, const KEY *key_info_p, const KEY *key_info_c) |
| Determine whether a cascaded update from the current state of the parent table record's foreign keys to the corresponding child table's foreign keys is legal. More... | |
| static int | extract_fk_from_record (uchar *out, const TABLE *table, const TABLE_SHARE_FOREIGN_KEY_INFO *fk, const uchar *record) |
| Extracts the current value of FK into a buffer. More... | |
| static bool | process_before_triggers (THD *thd, TABLE *table, const TABLE_SHARE_FOREIGN_KEY_INFO *fk, enum_trigger_event_type event, bool old_row_is_record1) |
| Executes BEFORE triggers for cascade operations when enabled and validate constraints if trigger updates any field. More... | |
| static bool | execute_after_triggers (THD *thd, TABLE *table, enum_trigger_event_type event, bool old_row_is_record1) |
| Executes AFTER triggers for cascade operations when enabled. More... | |
| static bool | on_delete_on_update_restrict_or_no_action (THD *thd, const TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk_c, enum_fk_dml_type dml_type) |
| Helper function to apply ON DELETE/ON UPDATE RESTRICT or NOACTION to child table on DML operation. More... | |
| static bool | on_delete_cascade (THD *thd, TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk_c, enum_fk_dml_type dml_type, uchar *key_value, int key_len, Foreign_key_chain *chain, int *error) |
| Helper function to apply ON DELETE CASCADE to child table on DML operation. More... | |
| static bool | on_update_cascade (THD *thd, const TABLE *table_p, TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk_c, KEY *key_info_p, uint parent_key_idx, KEY *key_info_c, uint child_key_idx, enum_fk_dml_type dml_type, uchar *key_value, int key_len, Foreign_key_chain *chain, int *error) |
| Function to apply ON UPDATE CASCADE to child table on DML operation. More... | |
| static bool | on_delete_on_update_set_null (THD *thd, const TABLE *table_p, TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk_c, enum_fk_dml_type dml_type, uchar *key_value, int key_len, Foreign_key_chain *chain, int *error) |
| Helper function to apply ON DELETE/ON UPDATE SET NULL to child table on DML operation. More... | |
| static bool | check_child_fk_ref (THD *thd, const TABLE *table_p, TABLE *table_c, TABLE_SHARE_FOREIGN_KEY_INFO *fk_c, enum_fk_dml_type dml_type, Foreign_key_chain *chain) |
| Checks foreign key constraint on child table. More... | |
| static bool | check_parent_fk_ref (THD *thd, const TABLE *table_c, TABLE *table_p, TABLE_SHARE_FOREIGN_KEY_INFO *fk, enum_fk_dml_type dml_type) |
| static bool | skip_foreign_key_checks (THD *thd, const TABLE *table) |
| Helper function to skip foreign checks. More... | |
| bool | check_all_parent_fk_ref (THD *thd, const TABLE *table_c, enum_fk_dml_type dml_type, const TABLE_SHARE_FOREIGN_KEY_INFO *ignore_fk) |
| Check all foreign key constraints on parent tables for DML operation on a child table. More... | |
| bool | check_all_child_fk_ref (THD *thd, const TABLE *table, enum_fk_dml_type dml_type) |
| Check all foreign key constraints on child tables for DML operation on a parent table. More... | |
| bool | is_foreign_key_table_opened (THD *thd, const char *db_name, const char *table_name, const char *fk_name, bool *is_unused_table) |
| Check if TABLE instance for foreign key is already opened. More... | |
Variables | |
| constexpr uint32_t | FK_MAX_CASCADE_DEPTH = 15 |
| With the ON CASCADE DELETE/UPDATE clause, deleting from the parent table can trigger recursive cascading calls. More... | |
| constexpr uint32_t | FK_MAX_TABLES_IN_CASCADE_CHAIN = 30 |
| With the ON CASCADE DELETE/UPDATE clause and triggers on child tables, multiple foreign key chains can form. More... | |
|
static |
Helper function to prepare error message.
| thd | Thread handle. |
| check_child_access | Check child table privileges. |
| check_parent_access | Check parent table privileges. |
| tbl | TABLE instance. |
| fk | Foreign Key Info instance. |
| bool check_all_child_fk_ref | ( | THD * | thd, |
| const TABLE * | table_p, | ||
| enum_fk_dml_type | dml_type | ||
| ) |
Check all foreign key constraints on child tables for DML operation on a parent table.
| thd | Thread handle. |
| table_p | TABLE instance of a parent table. |
| dml_type | DML operation type. |
|
static |
Check all foreign key constraints on child tables for DML operation on a parent table.
| thd | Thread handle. |
| table_p | TABLE instance of a parent table. |
| dml_type | DML operation type. |
| chain | Foreign key chain. |
| bool check_all_parent_fk_ref | ( | THD * | thd, |
| const TABLE * | table_c, | ||
| enum_fk_dml_type | dml_type, | ||
| const Table_share_foreign_key_info * | ignore_fk = nullptr |
||
| ) |
Check all foreign key constraints on parent tables for DML operation on a child table.
| thd | Thread handle. |
| table_c | TABLE instance of a child table. |
| dml_type | DML operation type. |
| ignore_fk | Skip FK check for this foreign key info |
During FK cascade, skip parent table foreign key value check because parent row is updated after updating the child row.
|
static |
Check if MDL lock is already acquired on the table.
If not, then acquire MDL lock on the schema and table.
| thd | Thread Handle. |
| db_name | DB name. |
| table_name | Table name. |
| mdl_type | MDL lock type. |
|
static |
Checks foreign key constraint on child table.
| thd | Thread Handle. |
| table_p | TABLE instance of a parent table. |
| table_c | TABLE instance of a child table. |
| fk_c | Foreign key information. |
| dml_type | DML operation type. |
| chain | Foreign key chain. |
|
static |
|
static |
Executes AFTER triggers for cascade operations when enabled.
| thd | Thread handle. |
| table | Table on which triggers should be fired. |
| event | Trigger event type. |
| old_row_is_record1 | If record1 contains old or new field. |
|
static |
Extracts the current value of FK into a buffer.
| [out] | out | Buffer to receive the FK columns' value. |
| table | TABLE instance containing the row. | |
| fk | FK info structure (for column list). | |
| record | Row buffer to extract from (table->record[0]). |
|
static |
Find TABLE instance of a foreign key table from the THD::open_tables list.
| thd | Thread Handle. |
| db_name | DB name. |
| table_name | Table name. |
| fk_name | Foreign key name. |
|
static |
Function to get TABLE instance of a other table in FK relationship.
Table is first searched in the open table list. If table is not opened or scan is already opened, then table is opened.
| thd | Thread Handle. | |
| db_name | DB name. | |
| table_name | Table name. | |
| fk_name | Foreign key name. If lock is not acquired, then MDL is acquired before opening the table. | |
| dml_type | DML operation type. If lock is not acquired, then MDL is acquired before opening the table. | |
| open_table | Do not search table in open_tables list, instead open table always. | |
| [out] | table | TABLE instance. |
| [out] | table_exists | Flag is set to true, if table does not exists. |
| [out] | is_table_opened | Flag is set to true, if a table is opened. |
|
static |
Function to get index of key matching col_names in keys list.
| table | TABLE instance. |
| num_columns | Number of columns. |
| col_names | List of column names. |
| bool is_cascade_from_parent_legal | ( | const TABLE * | table_p, |
| const KEY * | key_info_p, | ||
| const KEY * | key_info_c | ||
| ) |
Determine whether a cascaded update from the current state of the parent table record's foreign keys to the corresponding child table's foreign keys is legal.
An example of an illegal cascade is when a parent table foreign key column is a VARCHAR with a corresponding child foreign key CHAR column AND the length of the value in the parent column exceeds the number of characters allowed in the child column.
| table_p | parent table from which to check cascade. |
| key_info_p | descriptor of the foreign key index in the parent table. |
| key_info_c | descriptor of the foreign key index in the child table. |
| true | if the cascaded update is legal, false if the cascaded update is not legal. |
|
static |
Function to check if any of the foreign key columns updated.
| table | TABLE instance for a table. |
| num_key_cols | Number of columns. |
| col_names | List of columns. |
|
static |
Function to check if CASCADE action is defined for a foreign key on UPDATE or DELETE operations.
| table | TABLE instance of a table. |
| dml_type | DML operation type. |
| fk_name | Foreign key information. |
| bool is_foreign_key_table_opened | ( | THD * | thd, |
| const char * | db_name, | ||
| const char * | table_name, | ||
| const char * | fk_name, | ||
| bool * | is_unused_table | ||
| ) |
Check if TABLE instance for foreign key is already opened.
| thd | Thread handle. | |
| db_name | DB name. | |
| table_name | Table name. | |
| fk_name | Foreign key name. | |
| [out] | is_unused_table | Is set true if table exists in open table list but not in use. For instance tables locked under lock table, exists in open table list but not used. query_id for such tables is reset to 0 after statement execution. |
|
static |
Function to check value of foreign key columns and parent columns are same in case self referencing foreign key.
| table_c | TABLE instance of a table. |
| fk | Foreign key information. |
|
static |
Helper function to apply ON DELETE CASCADE to child table on DML operation.
| thd | Thread Handle. | |
| table_c | TABLE instance of a child table. | |
| fk_c | Foreign key information. | |
| dml_type | DML operation type. | |
| key_value | Key value buffer. | |
| key_len | Length of key value buffer. | |
| chain | Foreign key chain. | |
| [out] | error | Error value. |
|
static |
Helper function to apply ON DELETE/ON UPDATE RESTRICT or NOACTION to child table on DML operation.
Note: ON DELETE|UPDATE SET DEFAULT also behaves like RESTRICT
| thd | Thread Handle. |
| table_c | TABLE instance of a child table. |
| fk_c | Foreign key information. |
| dml_type | DML operation type. |
|
static |
Helper function to apply ON DELETE/ON UPDATE SET NULL to child table on DML operation.
| thd | Thread Handle. | |
| table_p | TABLE instance of a parent table. | |
| table_c | TABLE instance of a child table. | |
| fk_c | Foreign key information. | |
| dml_type | DML operation type. | |
| key_value | Key value buffer. | |
| key_len | Length of key value buffer. | |
| chain | Foreign key chain. | |
| [out] | error | Error value. |
|
static |
Function to apply ON UPDATE CASCADE to child table on DML operation.
| thd | Thread Handle. | |
| table_p | TABLE instance of a parent table. | |
| table_c | TABLE instance of a child table. | |
| fk_c | Foreign key information. | |
| dml_type | DML operation type. | |
| key_info_p | Parent table key information. | |
| parent_key_idx | Parent table key index. | |
| key_info_c | Child table key information. | |
| child_key_idx | Child table key index. | |
| key_value | Key value buffer. | |
| key_len | Length of key value buffer. | |
| chain | Foreign key chain. | |
| [out] | error | Error value. |
|
static |
Function to open table for foreign key validation.
| thd | Thread Handle. |
| db_name | DB name. |
| table_name | Table name. |
|
static |
Executes BEFORE triggers for cascade operations when enabled and validate constraints if trigger updates any field.
| thd | Thread handle. |
| table | Table on which triggers should be fired. |
| fk | Foreign key information |
| event | Trigger event type. |
| old_row_is_record1 | If record1 contains old or new field. |
|
inlinestatic |
Reports ER_NO_REFERENCED_ROW_2 error with fk information.
| thd | Thread Handle. |
| table_c | TABLE handle |
| fk | Foreign Key Information |
|
inlinestatic |
Reports ER_ROW_IS_REFERENCED_2 error with fk information.
| thd | Thread Handle. |
| table_c | TABLE handle |
| fk | Foreign Key Information |
|
static |
Function to set the null value for key columns.
| table | TABLE instance of a table. |
| num_key_cols | Number of columns. |
| col_names | List of columns. |
In stored functions/triggers, sub-statements follow the open-table call flow, so query_id ends up being set on the unused TABLE instance.
SQL FK handling does not go through the open-table call path. Therefore, we set query_id for the TABLE instance if enable_cascade_triggers=ON
| thd | Thread descriptor |
| table | Table Handle |
|
static |
Function to copy value to child table columns during UPDATE CASCADE operation.
| thd | Thread Handle. |
| table_c | TABLE instance of a child table. |
| child_key_idx | Index of key in the child table. |
| table_p | TABLE instance of a parent table. |
| parent_key_idx | Index of key in the parent table. |
| fk | Foreign key information. |
Helper function to skip foreign checks.
| thd | Thread Handle. |
| table | TABLE instance of a table. |
|
constexpr |
With the ON CASCADE DELETE/UPDATE clause, deleting from the parent table can trigger recursive cascading calls.
This defines the maximum number of such cascading deletes or updates allowed. If this limit is exceeded, the delete operation on the parent table will fail, and the user must drop the excessive foreign key constraint before proceeding.
|
constexpr |
With the ON CASCADE DELETE/UPDATE clause and triggers on child tables, multiple foreign key chains can form.
This constant defines the maximum number of tables allowed across such cascades. Exceeding the limit causes the parent-table operation to fail.