Commit 0d6a2180 authored by Marc Alff's avatar Marc Alff

Bug#34455 Ambiguous foreign keys syntax is accepted

Backport from 6.0 to 5.5
parent 372611d7
...@@ -13,3 +13,45 @@ foreign key (a,b) references t3 (c,d) on update set null); ...@@ -13,3 +13,45 @@ foreign key (a,b) references t3 (c,d) on update set null);
create index a on t1 (a); create index a on t1 (a);
create unique index b on t1 (a,b); create unique index b on t1 (a,b);
drop table t1; drop table t1;
drop table if exists t_34455;
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) match full match partial);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match partial)' at line 3
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) on delete set default match full);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 3
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) on update set default match full);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 3
create table t_34455 (
a int not null,
foreign key (a) references t3 (a)
on delete set default on delete set default);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete set default)' at line 4
create table t_34455 (
a int not null,
foreign key (a) references t3 (a)
on update set default on update set default);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update set default)' at line 4
create table t_34455 (a int not null);
alter table t_34455
add foreign key (a) references t3 (a) match full match partial);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match partial)' at line 2
alter table t_34455
add foreign key (a) references t3 (a) on delete set default match full);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 2
alter table t_34455
add foreign key (a) references t3 (a) on update set default match full);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'match full)' at line 2
alter table t_34455
add foreign key (a) references t3 (a)
on delete set default on delete set default);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete set default)' at line 3
alter table t_34455
add foreign key (a) references t3 (a)
on update set default on update set default);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update set default)' at line 3
drop table t_34455;
...@@ -23,3 +23,75 @@ create unique index b on t1 (a,b); ...@@ -23,3 +23,75 @@ create unique index b on t1 (a,b);
drop table t1; drop table t1;
# End of 4.1 tests # End of 4.1 tests
#
# Bug#34455 (Ambiguous foreign keys syntax is accepted)
#
--disable_warnings
drop table if exists t_34455;
--enable_warnings
# 2 match clauses, illegal
--error ER_PARSE_ERROR
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) match full match partial);
# match after on delete, illegal
--error ER_PARSE_ERROR
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) on delete set default match full);
# match after on update, illegal
--error ER_PARSE_ERROR
create table t_34455 (
a int not null,
foreign key (a) references t3 (a) on update set default match full);
# 2 on delete clauses, illegal
--error ER_PARSE_ERROR
create table t_34455 (
a int not null,
foreign key (a) references t3 (a)
on delete set default on delete set default);
# 2 on update clauses, illegal
--error ER_PARSE_ERROR
create table t_34455 (
a int not null,
foreign key (a) references t3 (a)
on update set default on update set default);
create table t_34455 (a int not null);
# 2 match clauses, illegal
--error ER_PARSE_ERROR
alter table t_34455
add foreign key (a) references t3 (a) match full match partial);
# match after on delete, illegal
--error ER_PARSE_ERROR
alter table t_34455
add foreign key (a) references t3 (a) on delete set default match full);
# match after on update, illegal
--error ER_PARSE_ERROR
alter table t_34455
add foreign key (a) references t3 (a) on update set default match full);
# 2 on delete clauses, illegal
--error ER_PARSE_ERROR
alter table t_34455
add foreign key (a) references t3 (a)
on delete set default on delete set default);
# 2 on update clauses, illegal
--error ER_PARSE_ERROR
alter table t_34455
add foreign key (a) references t3 (a)
on update set default on update set default);
drop table t_34455;
...@@ -1903,7 +1903,9 @@ struct LEX: public Query_tables_list ...@@ -1903,7 +1903,9 @@ struct LEX: public Query_tables_list
uint profile_options; uint profile_options;
uint uint_geom_type; uint uint_geom_type;
uint grant, grant_tot_col, which_columns; uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option; enum Foreign_key::fk_match_opt fk_match_option;
enum Foreign_key::fk_option fk_update_opt;
enum Foreign_key::fk_option fk_delete_opt;
uint slave_thd_opt, start_transaction_opt; uint slave_thd_opt, start_transaction_opt;
int nest_level; int nest_level;
/* /*
......
...@@ -756,6 +756,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, ...@@ -756,6 +756,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
struct p_elem_val *p_elem_value; struct p_elem_val *p_elem_value;
enum index_hint_type index_hint; enum index_hint_type index_hint;
enum enum_filetype filetype; enum enum_filetype filetype;
enum Foreign_key::fk_option m_fk_option;
Diag_condition_item_name diag_condition_item_name; Diag_condition_item_name diag_condition_item_name;
} }
...@@ -1422,7 +1423,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1422,7 +1423,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
type type_with_opt_collate int_type real_type order_dir lock_option type type_with_opt_collate int_type real_type order_dir lock_option
udf_type if_exists opt_local opt_table_options table_options udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog table_option opt_if_not_exists opt_no_write_to_binlog
delete_option opt_temporary all_or_any opt_distinct opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option opt_ignore_leaves fulltext_options spatial_type union_option
start_transaction_opts opt_chain opt_release start_transaction_opts opt_chain opt_release
union_opt select_derived_init option_type2 union_opt select_derived_init option_type2
...@@ -1430,6 +1431,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1430,6 +1431,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
%type <m_fk_option>
delete_option
%type <ulong_num> %type <ulong_num>
ulong_num real_ulong_num merge_insert_types ulong_num real_ulong_num merge_insert_types
...@@ -1544,7 +1548,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1544,7 +1548,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_precision opt_ignore opt_column opt_restrict opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary ascii unicode table_lock_list table_lock field_opt_list opt_binary ascii unicode table_lock_list table_lock
ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref opt_outer table_list table_name table_alias_ref_list table_alias_ref
opt_option opt_place opt_option opt_place
...@@ -5833,21 +5837,20 @@ opt_primary: ...@@ -5833,21 +5837,20 @@ opt_primary:
; ;
references: references:
REFERENCES table_ident REFERENCES
{ table_ident
LEX *lex=Lex;
lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0;
lex->ref_list.empty();
}
opt_ref_list opt_ref_list
opt_match_clause
opt_on_update_delete
{ {
$$=$2; $$=$2;
} }
; ;
opt_ref_list: opt_ref_list:
/* empty */ opt_on_delete {} /* empty */
| '(' ref_list ')' opt_on_delete {} { Lex->ref_list.empty(); }
| '(' ref_list ')'
; ;
ref_list: ref_list:
...@@ -5863,34 +5866,64 @@ ref_list: ...@@ -5863,34 +5866,64 @@ ref_list:
Key_part_spec *key= new Key_part_spec($1, 0); Key_part_spec *key= new Key_part_spec($1, 0);
if (key == NULL) if (key == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->ref_list.push_back(key); LEX *lex= Lex;
lex->ref_list.empty();
lex->ref_list.push_back(key);
} }
; ;
opt_on_delete: opt_match_clause:
/* empty */ {} /* empty */
| opt_on_delete_list {} { Lex->fk_match_option= Foreign_key::FK_MATCH_UNDEF; }
; | MATCH FULL
{ Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; }
opt_on_delete_list: | MATCH PARTIAL
opt_on_delete_list opt_on_delete_item {} { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; }
| opt_on_delete_item {} | MATCH SIMPLE_SYM
{ Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; }
; ;
opt_on_delete_item: opt_on_update_delete:
ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; } /* empty */
| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; } {
| MATCH FULL { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } LEX *lex= Lex;
| MATCH PARTIAL { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF;
| MATCH SIMPLE_SYM { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; } lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF;
}
| ON UPDATE_SYM delete_option
{
LEX *lex= Lex;
lex->fk_update_opt= $3;
lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF;
}
| ON DELETE_SYM delete_option
{
LEX *lex= Lex;
lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF;
lex->fk_delete_opt= $3;
}
| ON UPDATE_SYM delete_option
ON DELETE_SYM delete_option
{
LEX *lex= Lex;
lex->fk_update_opt= $3;
lex->fk_delete_opt= $6;
}
| ON DELETE_SYM delete_option
ON UPDATE_SYM delete_option
{
LEX *lex= Lex;
lex->fk_update_opt= $6;
lex->fk_delete_opt= $3;
}
; ;
delete_option: delete_option:
RESTRICT { $$= (int) Foreign_key::FK_OPTION_RESTRICT; } RESTRICT { $$= Foreign_key::FK_OPTION_RESTRICT; }
| CASCADE { $$= (int) Foreign_key::FK_OPTION_CASCADE; } | CASCADE { $$= Foreign_key::FK_OPTION_CASCADE; }
| SET NULL_SYM { $$= (int) Foreign_key::FK_OPTION_SET_NULL; } | SET NULL_SYM { $$= Foreign_key::FK_OPTION_SET_NULL; }
| NO_SYM ACTION { $$= (int) Foreign_key::FK_OPTION_NO_ACTION; } | NO_SYM ACTION { $$= Foreign_key::FK_OPTION_NO_ACTION; }
| SET DEFAULT { $$= (int) Foreign_key::FK_OPTION_DEFAULT; } | SET DEFAULT { $$= Foreign_key::FK_OPTION_DEFAULT; }
; ;
normal_key_type: normal_key_type:
......
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