mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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.
This commit is contained in:
@ -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` (
|
|||||||
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';
|
|||||||
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
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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,
|
|||||||
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 @@ remove_key:
|
|||||||
}
|
}
|
||||||
#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:
|
|||||||
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:
|
|||||||
{
|
{
|
||||||
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(
|
|||||||
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(
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user