Commit 22544004 authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-10421 duplicate CHECK CONSTRAINTs.

        mysql_prepare_create_table fixed so it doesn't let duplicating
        constraint names. Syntax for CONSTRAINT IF NOT EXISTS added
        and handled in mysql_alter_table.
parent 00dfe27f
...@@ -137,6 +137,7 @@ typedef unsigned long long my_ulonglong; ...@@ -137,6 +137,7 @@ typedef unsigned long long my_ulonglong;
/* backward compatibility define - to be removed eventually */ /* backward compatibility define - to be removed eventually */
#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED
#define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN
#define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME
typedef struct st_mysql_rows { typedef struct st_mysql_rows {
struct st_mysql_rows *next; /* list of rows */ struct st_mysql_rows *next; /* list of rows */
......
...@@ -2057,3 +2057,26 @@ t1 CREATE TABLE `t1` ( ...@@ -2057,3 +2057,26 @@ t1 CREATE TABLE `t1` (
KEY `i1` (`a`) COMMENT 'comment2' KEY `i1` (`a`) COMMENT 'comment2'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-10421 duplicate CHECK CONSTRAINTs
#
CREATE TABLE t1 (a INT, b INT) engine=myisam;
ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
ALTER TABLE t1 ADD CONSTRAINT `min` CHECK (a+b > 100);
ERROR HY000: Duplicate CHECK constraint name 'min'
ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
Warnings:
Note 1826 Duplicate CHECK constraint name 'min'
ALTER TABLE t1 ADD CONSTRAINT `mini` CHECK (a+b > 100);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
CONSTRAINT `min` CHECK (a+b > 100),
CONSTRAINT `mini` CHECK (a+b > 100)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(a INT, b INT, CONSTRAINT min check (a>5),
CONSTRAINT min check (b>5));
ERROR HY000: Duplicate CHECK constraint name 'min'
...@@ -1732,3 +1732,19 @@ ALTER TABLE t1 DROP INDEX i1, ADD INDEX i1(a) COMMENT 'comment2'; ...@@ -1732,3 +1732,19 @@ ALTER TABLE t1 DROP INDEX i1, ADD INDEX i1(a) COMMENT 'comment2';
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-10421 duplicate CHECK CONSTRAINTs
--echo #
CREATE TABLE t1 (a INT, b INT) engine=myisam;
ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
--error ER_DUP_CONSTRAINT_NAME
ALTER TABLE t1 ADD CONSTRAINT `min` CHECK (a+b > 100);
ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
ALTER TABLE t1 ADD CONSTRAINT `mini` CHECK (a+b > 100);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error ER_DUP_CONSTRAINT_NAME
CREATE TABLE t1(a INT, b INT, CONSTRAINT min check (a>5),
CONSTRAINT min check (b>5));
...@@ -6762,8 +6762,8 @@ ER_FK_CANNOT_OPEN_PARENT ...@@ -6762,8 +6762,8 @@ ER_FK_CANNOT_OPEN_PARENT
ER_FK_INCORRECT_OPTION ER_FK_INCORRECT_OPTION
eng "Failed to add the foreign key constraint on table '%s'. Incorrect options in FOREIGN KEY constraint '%s'" eng "Failed to add the foreign key constraint on table '%s'. Incorrect options in FOREIGN KEY constraint '%s'"
ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME
eng "Duplicate foreign key constraint name '%s'" eng "Duplicate %s constraint name '%s'"
ER_PASSWORD_FORMAT ER_PASSWORD_FORMAT
eng "The password hash doesn't have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function." eng "The password hash doesn't have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function."
......
...@@ -174,6 +174,8 @@ class Alter_info ...@@ -174,6 +174,8 @@ class Alter_info
List<Key> key_list; List<Key> key_list;
// List of columns, used by both CREATE and ALTER TABLE. // List of columns, used by both CREATE and ALTER TABLE.
List<Create_field> create_list; List<Create_field> create_list;
static const uint CHECK_CONSTRAINT_IF_NOT_EXISTS= 1;
List<Virtual_column_info> check_constraint_list; List<Virtual_column_info> check_constraint_list;
// Type of ALTER TABLE operation. // Type of ALTER TABLE operation.
uint flags; uint flags;
......
...@@ -3003,9 +3003,12 @@ struct LEX: public Query_tables_list ...@@ -3003,9 +3003,12 @@ struct LEX: public Query_tables_list
return false; return false;
} }
// Add a constraint as a part of CREATE TABLE or ALTER TABLE // Add a constraint as a part of CREATE TABLE or ALTER TABLE
bool add_constraint(LEX_STRING *name, Virtual_column_info *constr) bool add_constraint(LEX_STRING *name, Virtual_column_info *constr,
bool if_not_exists)
{ {
constr->name= *name; constr->name= *name;
constr->flags= if_not_exists ?
Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS : 0;
alter_info.check_constraint_list.push_back(constr); alter_info.check_constraint_list.push_back(constr);
return false; return false;
} }
......
...@@ -4201,6 +4201,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -4201,6 +4201,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
make_unique_constraint_name(thd, &check->name, make_unique_constraint_name(thd, &check->name,
&alter_info->check_constraint_list, &alter_info->check_constraint_list,
&nr); &nr);
{
/* Check that there's no repeating constraint names. */
List_iterator_fast<Virtual_column_info>
dup_it(alter_info->check_constraint_list);
Virtual_column_info *dup_check;
while ((dup_check= dup_it++) && dup_check != check)
{
if (check->name.length == dup_check->name.length &&
my_strcasecmp(system_charset_info,
check->name.str, dup_check->name.str) == 0)
{
my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name);
DBUG_RETURN(TRUE);
}
}
}
if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN, if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN,
system_charset_info, 1)) system_charset_info, 1))
...@@ -6153,6 +6169,39 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info) ...@@ -6153,6 +6169,39 @@ handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
} }
#endif /*WITH_PARTITION_STORAGE_ENGINE*/ #endif /*WITH_PARTITION_STORAGE_ENGINE*/
/* ADD CONSTRAINT IF NOT EXISTS. */
{
List_iterator<Virtual_column_info> it(alter_info->check_constraint_list);
Virtual_column_info *check;
TABLE_SHARE *share= table->s;
uint c;
while ((check=it++))
{
if ((!check->flags & Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS) &&
check->name.length)
continue;
check->flags= 0;
for (c= share->field_check_constraints;
c < share->table_check_constraints ; c++)
{
Virtual_column_info *dup= table->check_constraints[c];
if (dup->name.length == check->name.length &&
my_strcasecmp(system_charset_info,
check->name.str, dup->name.str) == 0)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DUP_CONSTRAINT_NAME, ER_THD(thd, ER_DUP_CONSTRAINT_NAME),
"CHECK", check->name.str);
it.remove();
if (alter_info->check_constraint_list.elements == 0)
alter_info->flags&= ~Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
break;
}
}
}
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -6073,7 +6073,7 @@ key_def: ...@@ -6073,7 +6073,7 @@ key_def:
constraint_def: constraint_def:
opt_constraint check_constraint opt_constraint check_constraint
{ {
Lex->add_constraint(&$1, $2); Lex->add_constraint(&$1, $2, FALSE);
} }
; ;
...@@ -7560,6 +7560,11 @@ alter_list_item: ...@@ -7560,6 +7560,11 @@ alter_list_item:
{ {
Lex->alter_info.flags|= Alter_info::ALTER_ADD_CHECK_CONSTRAINT; Lex->alter_info.flags|= Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
} }
| ADD CONSTRAINT IF_SYM not EXISTS field_ident check_constraint
{
Lex->alter_info.flags|= Alter_info::ALTER_ADD_CHECK_CONSTRAINT;
Lex->add_constraint(&$6, $7, TRUE);
}
| CHANGE opt_column opt_if_exists_table_element field_ident | CHANGE opt_column opt_if_exists_table_element field_ident
field_spec opt_place field_spec opt_place
{ {
......
...@@ -1125,9 +1125,9 @@ innobase_get_foreign_key_info( ...@@ -1125,9 +1125,9 @@ innobase_get_foreign_key_info(
referenced_column_names, referenced_num_col)) { referenced_column_names, referenced_num_col)) {
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
my_error( my_error(
ER_FK_DUP_NAME, ER_DUP_CONSTRAINT_NAME,
MYF(0), MYF(0),
add_fk[num_fk]->id); "FOREIGN KEY", add_fk[num_fk]->id);
goto err_exit; goto err_exit;
} }
......
...@@ -1128,9 +1128,9 @@ innobase_get_foreign_key_info( ...@@ -1128,9 +1128,9 @@ innobase_get_foreign_key_info(
referenced_column_names, referenced_num_col)) { referenced_column_names, referenced_num_col)) {
mutex_exit(&dict_sys->mutex); mutex_exit(&dict_sys->mutex);
my_error( my_error(
ER_FK_DUP_NAME, ER_DUP_CONSTRAINT_NAME,
MYF(0), MYF(0),
add_fk[num_fk]->id); "FOREIGN KEY", add_fk[num_fk]->id);
goto err_exit; goto err_exit;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment