mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-22602 Disable UPDATE CASCADE for SQL constraints
CHECK constraint is checked by check_expression() which walks its items and gets into Item_field::check_vcol_func_processor() to check for conformity with foreign key list. WITHOUT OVERLAPS is checked for same conformity in mysql_prepare_create_table(). Long uniques are already impossible with InnoDB foreign keys. See ER_CANT_CREATE_TABLE in test case. 2 accompanying bugs fixed (test main.constraints failed): 1. check->name.str lived on SP execute mem_root while "check" obj itself lives on SP main mem_root. On second SP execute check->name.str had garbage data. Fixed by allocating from thd->stmt_arena->mem_root which is SP main mem_root. 2. CHECK_CONSTRAINT_IF_NOT_EXISTS value was mixed with VCOL_FIELD_REF. VCOL_FIELD_REF is assigned in check_expression() and then detected as CHECK_CONSTRAINT_IF_NOT_EXISTS in handle_if_exists_options(). Existing cases for MDEV-16932 in main.constraints cover both fixes.
This commit is contained in:
@ -4292,9 +4292,31 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
key_info->algorithm == HA_KEY_ALG_LONG_HASH)
|
||||
|
||||
{
|
||||
without_overlaps_err:
|
||||
my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key_info->name.str);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
key_iterator2.rewind();
|
||||
while ((key2 = key_iterator2++))
|
||||
{
|
||||
if (key2->type != Key::FOREIGN_KEY)
|
||||
continue;
|
||||
DBUG_ASSERT(key != key2);
|
||||
Foreign_key *fk= (Foreign_key*) key2;
|
||||
if (fk->update_opt != FK_OPTION_CASCADE)
|
||||
continue;
|
||||
for (Key_part_spec& kp: key->columns)
|
||||
{
|
||||
for (Key_part_spec& kp2: fk->columns)
|
||||
{
|
||||
if (!lex_string_cmp(system_charset_info, &kp.field_name,
|
||||
&kp2.field_name))
|
||||
{
|
||||
goto without_overlaps_err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
create_info->period_info.unique_keys++;
|
||||
}
|
||||
|
||||
@ -4383,7 +4405,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
while ((check= c_it++))
|
||||
{
|
||||
if (!check->name.length || check->automatic_name)
|
||||
{
|
||||
if (check_expression(check, &check->name, VCOL_CHECK_TABLE, alter_info))
|
||||
DBUG_RETURN(TRUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
/* Check that there's no repeating table CHECK constraint names. */
|
||||
@ -5538,7 +5564,7 @@ static bool make_unique_constraint_name(THD *thd, LEX_CSTRING *name,
|
||||
if (!check) // Found unique name
|
||||
{
|
||||
name->length= (size_t) (real_end - buff);
|
||||
name->str= thd->strmake(buff, name->length);
|
||||
name->str= strmake_root(thd->stmt_arena->mem_root, buff, name->length);
|
||||
return (name->str == NULL);
|
||||
}
|
||||
}
|
||||
@ -6666,7 +6692,7 @@ remove_key:
|
||||
|
||||
while ((check=it++))
|
||||
{
|
||||
if (!(check->flags & Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS) &&
|
||||
if (!(check->flags & VCOL_CHECK_CONSTRAINT_IF_NOT_EXISTS) &&
|
||||
check->name.length)
|
||||
continue;
|
||||
check->flags= 0;
|
||||
|
Reference in New Issue
Block a user