← Back to team overview

maria-developers team mailing list archive

Please review MDEV-7284 INDEX: CREATE OR REPLACE

 

Hi Sergei,

Please review a patch for MDEV-7284

Thanks.
diff --git a/mysql-test/r/create_drop_binlog.result b/mysql-test/r/create_drop_binlog.result
index f7aaedf..6db54a6 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 0000000..113c32a
--- /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 0000000..1126c7e
--- /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 0000000..ee183ac
--- /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 2a0f183..775c7be 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 0000000..4c86126
--- /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 a0da5a9..98f8a8a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -2866,7 +2866,8 @@ struct LEX: public Query_tables_list
   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 c4b07ad..4550b10 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5830,7 +5830,7 @@ static bool is_candidate_key(KEY *key)
     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 @@ static bool is_candidate_key(KEY *key)
       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 1153ff8..8a39e62 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

Follow ups