1
0
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:
Aleksey Midenkov
2020-06-12 11:10:55 +03:00
parent 02c255d1e0
commit 762bf7a03b
10 changed files with 110 additions and 24 deletions

View File

@ -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;