WL#6555: Online rename index

Affects: Server-5.7   —   Status: Complete   —   Priority: Medium

We want to allow online index rename. The proposed syntax is:

ALTER TABLE ... RENAME INDEX xxx TO yyy

This WL depends on changes to MySQL parser, as well as MDL
Syntax changes
==============

Grammar for ALTER TABLE is adjusted to support new clause for renaming
of indexes. This is done by adding new alternative for <alter_list_item>
rule:

<alter_specification> ::= <add column clause> | .. | <alter_lock_option> |
                          <rename index clause>

Where:

<rename index clause> ::= RENAME ( INDEX | KEY ) <oldname> TO <newname>

<oldname> ::= <field_ident>
<newname> ::= <field_ident>

Semantics
=========

<oldname> should be name of existing index in table being altered, which
is not dropped by the same alter table. <oldname> should not be equal to
'primary' (this limitation can be relaxed).

<newname> is new name for the index being renamed, should not coincide
with name of any existing index which is not dropped within the same
alter table or index added by the same alter table. <newname> should
not be equal to 'primary' (this limitation is harder to relax).

If any of these preconditions fail an appropriate error is emitted.

The result of "ALTER TABLE t1 RENAME INDEX a TO b" is table which
contents and structure is identical to old version of 't1' with
the only exception index 'a' being called 'b'.

Support of this clause in default implementation of ALTER TABLE,
(i.e. using COPY algorithm) is trivial as we simply need adjust
name of index being renamed when we construct key description to
be passed to mysql_prepare_create_table() for new version of table.
The process of copying between old and new version is not affected
by this clause at all.

Note that <field_ident> is used here instead of <ident> mostly for
the sake of consistency with other clauses in ALTER TABLE.

Changes to in-place SE API
==========================

Since the main goal of this task is to support RENAME INDEX as in-place/
online operation proper representation in in-place SE API is important.

New flag for Alter_inplace_info::handler_flags bitmap is introduced -
Alter_inplace_info::RENAME_INDEX.

This flag is set when at least one index is renamed by this ALTER TABLE.
The flag should not be set if index in question is changed otherwise
(e.g. number of columns in it is decreased). We treat such cases as
dropping of old and addition of new index. For simplicity, we don't
set this flag in cases when user renames index by explicitly dropping
index and then creating new index which has identical structure but
differs in name. If needed such optimization can be introduced later.

New members are added to Alter_inplace_info class:
  rename_index_buffer - an array of pairs of pointers to new and old
  versions of KEY for each index renamed (in key_buffer_info and 
  TABLE::keyinfo correspondingly).
  rename_index_count - number of renamed indexes.

TODO: check with InnoDB that the above is what they really want.

Changes to InnoDB
=================
Implementation of support for inplace/online rename indexes in
InnoDB within responsibility of InnoDB team. We will simply add
Alter_inplace_info::RENAME_INDEX flag to the bitmap of offline
operations for InnoDB as a temporary stub.

Changes to other engines
========================
Since implementing support for in-place RENAME INDEX is trivial
for MyISAM, Heap and other simplistic storage engines we will
support them as well. These engines don't store names of so
implementation of such support boils down to enabling in-place
RENAME INDEX by properly reacting to RENAME_INDEX flag on handler
layer.
Detailed changes to storage engine API
======================================

Introduce a structure that will describe changes to
and index to be caused by ALTER TABLE by referencing
KEY objects for old and new version of index:

struct KEY_PAIR
{
  /**
    Pointer to KEY object describing old version of index in
    TABLE::key_info array for TABLE instance representing old
    version of table.
  */
  KEY *old_key;
  /**
    Pointer to KEY object describing new version of index in
    Alter_inplace_info::key_info_buffer array.
  */
  KEY *new_key;
};


Add a new flag to Alter_inplace_info::HA_ALTER_FLAGS:

/**
  Rename index. Note that we set this flag only if there are no other
  changes to the index being renamed. Also for simplicity we don't
  detect renaming of indexes which is done by dropping index and then
  re-creating index with identical definition under different name.
*/
static const HA_ALTER_FLAGS RENAME_INDEX = ...;

Add two more members to Alter_inplace_info:

/** Size of index_rename_buffer array. */
uint index_rename_count;

/**
  Array of KEY_PAIR objects describing indexes being renamed.
  For each index renamed it contains object with KEY_PAIR::old_key
  pointing to KEY object belonging to the TABLE instance for old
  version of table representing old version of index and with
  KEY_PAIR::new_key pointing to KEY object for new version of
  index in key_info_buffer member.
*/
KEY_PAIR  *index_rename_buffer;