diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2016-09-06 14:42:33 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2016-09-06 14:42:33 +0400 |
commit | 225440047d145bbe6a92bff05c5d4aa33e0aca91 (patch) | |
tree | 96d93f29a84df1fe66bdabfcc8fd20c9fc326013 | |
parent | 00dfe27f7c5a0382d16cac832e879ae9f1cc45e9 (diff) | |
download | mariadb-git-225440047d145bbe6a92bff05c5d4aa33e0aca91.tar.gz |
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.
-rw-r--r-- | include/mysql.h | 1 | ||||
-rw-r--r-- | mysql-test/r/alter_table.result | 23 | ||||
-rw-r--r-- | mysql-test/t/alter_table.test | 16 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 4 | ||||
-rw-r--r-- | sql/sql_alter.h | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 49 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 7 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 4 | ||||
-rw-r--r-- | storage/xtradb/handler/handler0alter.cc | 4 |
10 files changed, 107 insertions, 8 deletions
diff --git a/include/mysql.h b/include/mysql.h index 19099b4f404..eab859270f7 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -137,6 +137,7 @@ typedef unsigned long long my_ulonglong; /* backward compatibility define - to be removed eventually */ #define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED #define WARN_PLUGIN_DELETE_BUILTIN ER_PLUGIN_DELETE_BUILTIN +#define ER_FK_DUP_NAME ER_DUP_CONSTRAINT_NAME typedef struct st_mysql_rows { struct st_mysql_rows *next; /* list of rows */ diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 0801890c384..de93fab4c9e 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -2057,3 +2057,26 @@ t1 CREATE TABLE `t1` ( KEY `i1` (`a`) COMMENT 'comment2' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 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' diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 7811de0f9f7..1ff38e4807f 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1732,3 +1732,19 @@ ALTER TABLE t1 DROP INDEX i1, ADD INDEX i1(a) COMMENT 'comment2'; SHOW CREATE 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)); + + diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 43de678e1c2..37012c17bfb 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6762,8 +6762,8 @@ ER_FK_CANNOT_OPEN_PARENT ER_FK_INCORRECT_OPTION eng "Failed to add the foreign key constraint on table '%s'. Incorrect options in FOREIGN KEY constraint '%s'" -ER_FK_DUP_NAME - eng "Duplicate foreign key constraint name '%s'" +ER_DUP_CONSTRAINT_NAME + eng "Duplicate %s constraint name '%s'" 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." diff --git a/sql/sql_alter.h b/sql/sql_alter.h index 9e5fbaa425f..faba3a14a1b 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -174,6 +174,8 @@ public: List<Key> key_list; // List of columns, used by both CREATE and ALTER TABLE. List<Create_field> create_list; + + static const uint CHECK_CONSTRAINT_IF_NOT_EXISTS= 1; List<Virtual_column_info> check_constraint_list; // Type of ALTER TABLE operation. uint flags; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e03446010b6..af461d05036 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3003,9 +3003,12 @@ public: return false; } // 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->flags= if_not_exists ? + Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS : 0; alter_info.check_constraint_list.push_back(constr); return false; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7784a2b188a..80fadde714f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4201,6 +4201,22 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, make_unique_constraint_name(thd, &check->name, &alter_info->check_constraint_list, &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, system_charset_info, 1)) @@ -6153,6 +6169,39 @@ remove_key: } #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; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 63ba77caa22..5908c7d3cb8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6073,7 +6073,7 @@ key_def: constraint_def: opt_constraint check_constraint { - Lex->add_constraint(&$1, $2); + Lex->add_constraint(&$1, $2, FALSE); } ; @@ -7560,6 +7560,11 @@ alter_list_item: { 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 field_spec opt_place { diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index bb7efa104fa..29d49dcce9f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1125,9 +1125,9 @@ innobase_get_foreign_key_info( referenced_column_names, referenced_num_col)) { mutex_exit(&dict_sys->mutex); my_error( - ER_FK_DUP_NAME, + ER_DUP_CONSTRAINT_NAME, MYF(0), - add_fk[num_fk]->id); + "FOREIGN KEY", add_fk[num_fk]->id); goto err_exit; } diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 5724d9fe8ff..7459c4c4199 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1128,9 +1128,9 @@ innobase_get_foreign_key_info( referenced_column_names, referenced_num_col)) { mutex_exit(&dict_sys->mutex); my_error( - ER_FK_DUP_NAME, + ER_DUP_CONSTRAINT_NAME, MYF(0), - add_fk[num_fk]->id); + "FOREIGN KEY", add_fk[num_fk]->id); goto err_exit; } |