diff --git a/mysql-test/r/create_drop_binlog.result b/mysql-test/r/create_drop_binlog.result index f7aaedf9118..6db54a6997a 100644 --- a/mysql-test/r/create_drop_binlog.result +++ b/mysql-test/r/create_drop_binlog.result @@ -304,3 +304,32 @@ Log_name Pos Event_type Server_id End_log_pos Info # # Gtid 1 # GTID #-#-# # # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */ RESET MASTER; +CREATE TABLE t1(a INT, b INT); +CREATE TABLE IF NOT EXISTS t1(a INT, b INT); +Warnings: +Note 1050 Table 't1' already exists +CREATE OR REPLACE INDEX i1 ON t1(a); +CREATE OR REPLACE INDEX i1 ON t1(a); +CREATE OR REPLACE INDEX i1 ON t1(a,b); +CREATE OR REPLACE INDEX i1 ON t1(a,b); +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +# # Format_desc 1 # VER +# # Gtid_list 1 # [] +# # Binlog_checkpoint 1 # master-bin.000001 +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE TABLE t1(a INT, b INT) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE TABLE IF NOT EXISTS t1(a INT, b INT) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a,b) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; CREATE OR REPLACE INDEX i1 ON t1(a,b) +# # Gtid 1 # GTID #-#-# +# # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */ +RESET MASTER; diff --git a/mysql-test/r/create_drop_index.result b/mysql-test/r/create_drop_index.result new file mode 100644 index 00000000000..113c32aca4d --- /dev/null +++ b/mysql-test/r/create_drop_index.result @@ -0,0 +1,44 @@ +CREATE TABLE t1(a INT, b INT); +CREATE INDEX IF NOT EXISTS i1 ON t1(a); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `i1` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP INDEX IF EXISTS i1 ON t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP INDEX IF EXISTS i1 ON t1; +Warnings: +Note 1091 Can't DROP 'i1'; check that column/key exists +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +CREATE OR REPLACE INDEX i1 ON t1(a); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `i1` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +CREATE OR REPLACE INDEX i1 ON t1(a,b); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `i1` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE OR REPLACE INDEX IF NOT EXISTS i1 ON t1(b,a); +ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS diff --git a/mysql-test/suite/rpl/r/rpl_create_drop_index.result b/mysql-test/suite/rpl/r/rpl_create_drop_index.result new file mode 100644 index 00000000000..1126c7eb701 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_create_drop_index.result @@ -0,0 +1,23 @@ +include/master-slave.inc +[connection master] +CREATE TABLE t1 (a INT, b INT); +CREATE INDEX i1 ON t1 (a); +CREATE OR REPLACE INDEX i1 ON t1 (a, b); +# On slave: +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `i1` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +# On master: +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + KEY `i1` (`a`,`b`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_drop_index.test b/mysql-test/suite/rpl/t/rpl_create_drop_index.test new file mode 100644 index 00000000000..ee183ac331b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_drop_index.test @@ -0,0 +1,19 @@ +--source include/master-slave.inc + +connection master; + +CREATE TABLE t1 (a INT, b INT); +CREATE INDEX i1 ON t1 (a); +CREATE OR REPLACE INDEX i1 ON t1 (a, b); +sync_slave_with_master; + +--echo # On slave: +SHOW CREATE TABLE t1; + +connection master; +--echo # On master: +SHOW CREATE TABLE t1; +DROP TABLE t1; +sync_slave_with_master; + +--source include/rpl_end.inc diff --git a/mysql-test/t/create_drop_binlog.test b/mysql-test/t/create_drop_binlog.test index 2a0f183d5d8..775c7bec12a 100644 --- a/mysql-test/t/create_drop_binlog.test +++ b/mysql-test/t/create_drop_binlog.test @@ -147,3 +147,16 @@ DROP TABLE t1; --replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/ SHOW BINLOG EVENTS; RESET MASTER; + + +CREATE TABLE t1(a INT, b INT); +CREATE TABLE IF NOT EXISTS t1(a INT, b INT); +CREATE OR REPLACE INDEX i1 ON t1(a); +CREATE OR REPLACE INDEX i1 ON t1(a); +CREATE OR REPLACE INDEX i1 ON t1(a,b); +CREATE OR REPLACE INDEX i1 ON t1(a,b); +DROP TABLE t1; +--replace_column 1 # 2 # 5 # +--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/ +SHOW BINLOG EVENTS; +RESET MASTER; diff --git a/mysql-test/t/create_drop_index.test b/mysql-test/t/create_drop_index.test new file mode 100644 index 00000000000..4c861266325 --- /dev/null +++ b/mysql-test/t/create_drop_index.test @@ -0,0 +1,16 @@ +CREATE TABLE t1(a INT, b INT); +CREATE INDEX IF NOT EXISTS i1 ON t1(a); +SHOW CREATE TABLE t1; +DROP INDEX IF EXISTS i1 ON t1; +SHOW CREATE TABLE t1; +DROP INDEX IF EXISTS i1 ON t1; +SHOW CREATE TABLE t1; + +CREATE OR REPLACE INDEX i1 ON t1(a); +SHOW CREATE TABLE t1; +CREATE OR REPLACE INDEX i1 ON t1(a,b); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_WRONG_USAGE +CREATE OR REPLACE INDEX IF NOT EXISTS i1 ON t1(b,a); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 03e97b3d54a..e7c4ae0e770 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2866,7 +2866,8 @@ public: bool add_create_index(Key::Keytype type, const LEX_STRING &name, ha_key_alg algorithm, DDL_options_st ddl) { - if (!(last_key= new Key(type, name, algorithm, false, ddl))) + if (check_create_options(ddl) || + !(last_key= new Key(type, name, algorithm, false, ddl))) return true; alter_info.key_list.push_back(last_key); return false; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c4b07ad2035..4550b10c40c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5830,7 +5830,7 @@ drop_create_field: const char *keyname; while ((key=key_it++)) { - if (!key->if_not_exists()) + if (!key->if_not_exists() && !key->or_replace()) continue; /* If the name of the key is not specified, */ /* let us check the name of the first key part. */ @@ -5891,17 +5891,32 @@ drop_create_field: continue; remove_key: - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), keyname); - key_it.remove(); - if (key->type == Key::FOREIGN_KEY) + if (key->if_not_exists()) { - /* ADD FOREIGN KEY appends two items. */ + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), keyname); key_it.remove(); + if (key->type == Key::FOREIGN_KEY) + { + /* ADD FOREIGN KEY appends two items. */ + key_it.remove(); + } + if (alter_info->key_list.is_empty()) + alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX | + Alter_info::ADD_FOREIGN_KEY); + } + else if (key->or_replace()) + { + Alter_drop::drop_type type= (key->type == Key::FOREIGN_KEY) ? + Alter_drop::FOREIGN_KEY : Alter_drop::KEY; + Alter_drop *ad= new Alter_drop(type, key->name.str, FALSE); + if (ad != NULL) + { + // Adding the index into the drop list for replacing + alter_info->flags |= Alter_info::ALTER_DROP_INDEX; + alter_info->drop_list.push_back(ad); + } } - if (alter_info->key_list.is_empty()) - alter_info->flags&= ~(Alter_info::ALTER_ADD_INDEX | - Alter_info::ADD_FOREIGN_KEY); } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1153ff867e9..8a39e627b55 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2487,31 +2487,33 @@ create: } create_table_set_open_action_and_adjust_tables(lex); } - | CREATE opt_unique INDEX_SYM opt_if_not_exists ident + | create_or_replace opt_unique INDEX_SYM opt_if_not_exists ident opt_key_algorithm_clause ON table_ident { if (add_create_index_prepare(Lex, $8)) MYSQL_YYABORT; - if (Lex->add_create_index($2, $5, $6, $4)) + if (Lex->add_create_index($2, $5, $6, $1 | $4)) MYSQL_YYABORT; } '(' key_list ')' normal_key_options opt_index_lock_algorithm { } - | CREATE fulltext INDEX_SYM opt_if_not_exists ident ON table_ident + | create_or_replace fulltext INDEX_SYM opt_if_not_exists ident + ON table_ident { if (add_create_index_prepare(Lex, $7)) MYSQL_YYABORT; - if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $4)) + if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4)) MYSQL_YYABORT; } '(' key_list ')' fulltext_key_options opt_index_lock_algorithm { } - | CREATE spatial INDEX_SYM opt_if_not_exists ident ON table_ident + | create_or_replace spatial INDEX_SYM opt_if_not_exists ident + ON table_ident { if (add_create_index_prepare(Lex, $7)) MYSQL_YYABORT; - if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $4)) + if (Lex->add_create_index($2, $5, HA_KEY_ALG_UNDEF, $1 | $4)) MYSQL_YYABORT; } '(' key_list ')' spatial_key_options