summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-03-03 13:50:33 +0300
committerAleksey Midenkov <midenok@gmail.com>2020-03-03 13:50:33 +0300
commit193725b81ed813d0318c1fa82de284c337246d9e (patch)
tree5491a62650565a58d24cfc629b7466f29b617d18 /sql
parentfa8ad7543947f5c74dece982d42bab59b6479449 (diff)
downloadmariadb-git-193725b81ed813d0318c1fa82de284c337246d9e.tar.gz
MDEV-7318 RENAME INDEX
This patch adds support of RENAME INDEX operation to the ALTER TABLE statement. Code which determines if ALTER TABLE can be done in-place for "simple" storage engines like MyISAM, Heap and etc. was updated to handle ALTER TABLE ... RENAME INDEX as an in-place operation. Support for in-place ALTER TABLE ... RENAME INDEX for InnoDB was covered by MDEV-13301. Syntax changes ============== A new type of <alter_specification> is added: <rename index clause> ::= RENAME ( INDEX | KEY ) <oldname> TO <newname> Where <oldname> and <newname> are identifiers for old name and new name of the index. Semantic changes ================ The result of "ALTER TABLE t1 RENAME INDEX a TO b" is a table which contents and structure are identical to the old version of 't1' with the only exception index 'a' being called 'b'. Neither <oldname> nor <newname> can be "primary". The index being renamed should exist and its new name should not be occupied by another index on the same table. Related to: WL#6555, MDEV-13301
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/sql_alter.cc2
-rw-r--r--sql/sql_alter.h4
-rw-r--r--sql/sql_class.h15
-rw-r--r--sql/sql_table.cc43
-rw-r--r--sql/sql_yacc.yy10
6 files changed, 75 insertions, 2 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 7d61252eea6..806d91bdbc5 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4585,7 +4585,8 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
ALTER_DROP_CHECK_CONSTRAINT |
ALTER_PARTITIONED |
ALTER_VIRTUAL_GCOL_EXPR |
- ALTER_RENAME;
+ ALTER_RENAME |
+ ALTER_RENAME_INDEX;
/* Is there at least one operation that requires copy algorithm? */
if (ha_alter_info->handler_flags & ~inplace_offline_operations)
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 0828e1b7ba8..23e2e3e097f 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -25,6 +25,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
+ alter_rename_key_list(rhs.alter_rename_key_list, mem_root),
create_list(rhs.create_list, mem_root),
check_constraint_list(rhs.check_constraint_list, mem_root),
flags(rhs.flags), partition_flags(rhs.partition_flags),
@@ -46,6 +47,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
list_copy_and_replace_each_value(drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
+ list_copy_and_replace_each_value(alter_rename_key_list, mem_root);
list_copy_and_replace_each_value(create_list, mem_root);
/* partition_names are not deeply copied currently */
}
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 41408a91836..a553c31346a 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -19,6 +19,7 @@
class Alter_drop;
class Alter_column;
+class Alter_rename_key;
class Key;
/**
@@ -87,6 +88,8 @@ public:
List<Alter_column> alter_list;
// List of keys, used by both CREATE and ALTER TABLE.
List<Key> key_list;
+ // List of keys to be renamed.
+ List<Alter_rename_key> alter_rename_key_list;
// List of columns, used by both CREATE and ALTER TABLE.
List<Create_field> create_list;
@@ -123,6 +126,7 @@ public:
drop_list.empty();
alter_list.empty();
key_list.empty();
+ alter_rename_key_list.empty();
create_list.empty();
check_constraint_list.empty();
flags= 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6a7c0cd4d94..123bf0c0583 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -355,6 +355,21 @@ public:
};
+class Alter_rename_key : public Sql_alloc
+{
+public:
+ LEX_CSTRING old_name;
+ LEX_CSTRING new_name;
+
+ Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg)
+ : old_name(old_name_arg), new_name(new_name_arg) {}
+
+ Alter_rename_key *clone(MEM_ROOT *mem_root) const
+ { return new (mem_root) Alter_rename_key(*this); }
+
+};
+
+
class Key :public Sql_alloc, public DDL_options {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b5cc07b1411..3b56a721801 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6601,7 +6601,7 @@ static int compare_uint(const uint *s, const uint *t)
enum class Compare_keys : uint32_t
{
- Equal,
+ Equal= 0,
EqualButKeyPartLength,
EqualButComment,
NotEqual
@@ -7998,6 +7998,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
List<Create_field> new_create_list;
/* New key definitions are added here */
List<Key> new_key_list;
+ List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -8446,6 +8447,39 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
+ /* If this index is to stay in the table check if it has to be renamed. */
+ List_iterator<Alter_rename_key> rename_key_it(rename_key_list);
+ Alter_rename_key *rename_key;
+
+ while ((rename_key= rename_key_it++))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, rename_key->old_name.str))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name.str);
+ goto err;
+ }
+ else if (!my_strcasecmp(system_charset_info, rename_key->new_name.str,
+ primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name.str);
+ goto err;
+ }
+
+ key_name= rename_key->new_name.str;
+ rename_key_it.remove();
+ /*
+ If the user has explicitly renamed the key, we should no longer
+ treat it as generated. Otherwise this key might be automatically
+ dropped by mysql_prepare_create_table() and this will confuse
+ code in fill_alter_inplace_info().
+ */
+ key_info->flags&= ~HA_GENERATED_KEY;
+ break;
+ }
+ }
+
if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
{
setup_keyinfo_hash(key_info);
@@ -8772,6 +8806,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
+ if (rename_key_list.elements)
+ {
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list.head()->old_name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+
if (!create_info->comment.str)
{
create_info->comment.str= table->s->comment.str;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1d4a8a7e228..b032ce66cc7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7732,6 +7732,16 @@ alter_list_item:
if (unlikely(Lex->add_alter_list($3, $5)))
MYSQL_YYABORT;
}
+ | RENAME key_or_index field_ident TO_SYM field_ident
+ {
+ LEX *lex=Lex;
+ Alter_rename_key *ak= new (thd->mem_root)
+ Alter_rename_key($3, $5);
+ if (ak == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.alter_rename_key_list.push_back(ak);
+ lex->alter_info.flags|= ALTER_RENAME_INDEX;
+ }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{
if (!$4)