1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).

Syntax modified to allow statements:
               ALTER TABLE ADD/DROP COLUMN
               ALTER TABLE ADD/DROP INDEX
               ALTER TABLE ADD/DROP FOREIGN KEY
               ALTER TABLE ADD/DROP PARTITION
               ALTER TABLE CHANGE COLUMN
               ALTER TABLE MODIFY COLUMN
               DROP INDEX
         to have IF (NOT) EXISTS options.
         Appropriate implementations added to mysql_alter_table().
      
      per-file comments:
        mysql-test/r/alter_table.result
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              test result updated.
        mysql-test/r/fulltext.result
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
        mysql-test/r/partition.result
              test result updated.
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
        mysql-test/t/alter_table.test
              tests added.
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
        mysql-test/t/fulltext.test
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              tests added.
        mysql-test/t/partition.test
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              tests added.
        sql/field.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              create_if_not_exists field added.
        sql/field.h
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              create_if_not_exists field added.
        sql/partition_info.h
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              has_unique_name made public.
        sql/sp_head.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
        sql/sql_class.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              create_if_not_exists inited.
        sql/sql_class.h
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              create_if_not_exists inited.
        sql/sql_lex.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              check_exists inited.
        sql/sql_lex.h
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              check_exists inited.
        sql/sql_parse.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
        check_exists inited.
        sql/sql_table.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              handle_if_exists_options() added.
              it's called in mysql_alter_table().
        sql/sql_trigger.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              check_exists instead of drop_if_exists.
        sql/sql_view.cc
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              check_exists instead of drop_if_exists.
        sql/sql_yacc.yy
      MDEV-318 IF (NOT) EXIST clauses for ALTER TABLE (MWL #252).
              sintax modified.
This commit is contained in:
Alexey Botchkov
2013-04-13 11:59:16 +05:00
parent 1a600125ff
commit d8dccde6df
19 changed files with 523 additions and 88 deletions

View File

@ -4953,6 +4953,246 @@ is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
}
/*
Preparation for table creation
SYNOPSIS
handle_if_exists_option()
thd Thread object.
table The altered table.
alter_info List of columns and indexes to create
DESCRIPTION
Looks for the IF [NOT] EXISTS options, checks the states and remove items
from the list if existing found.
RETURN VALUES
NONE
*/
static void
handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
{
Field **f_ptr;
DBUG_ENTER("handle_if_exists_option");
/* Handle ADD COLUMN IF NOT EXISTS. */
{
List_iterator<Create_field> it(alter_info->create_list);
Create_field *sql_field;
while ((sql_field=it++))
{
if (!sql_field->create_if_not_exists || sql_field->change)
continue;
/*
If there is a field with the same name in the table already,
remove the sql_field from the list.
*/
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
sql_field->field_name, (*f_ptr)->field_name) == 0)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DUP_FIELDNAME, ER(ER_DUP_FIELDNAME),
sql_field->field_name);
it.remove();
if (alter_info->create_list.is_empty())
{
alter_info->flags&= ~ALTER_ADD_COLUMN;
if (alter_info->key_list.is_empty())
alter_info->flags&= ~ALTER_ADD_INDEX;
}
break;
}
}
}
}
/* Handle MODIFY COLUMN IF EXISTS. */
{
List_iterator<Create_field> it(alter_info->create_list);
Create_field *sql_field;
while ((sql_field=it++))
{
if (!sql_field->create_if_not_exists || !sql_field->change)
continue;
/*
If there is NO field with the same name in the table already,
remove the sql_field from the list.
*/
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
sql_field->field_name, (*f_ptr)->field_name) == 0)
{
break;
}
}
if (*f_ptr == NULL)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
sql_field->change, table->s->table_name.str);
it.remove();
if (alter_info->create_list.is_empty())
{
alter_info->flags&= ~(ALTER_ADD_COLUMN | ALTER_CHANGE_COLUMN);
if (alter_info->key_list.is_empty())
alter_info->flags&= ~ALTER_ADD_INDEX;
}
}
}
}
/* Handle DROP COLUMN/KEY IF EXISTS. */
{
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
Alter_drop *drop;
bool remove_drop;
while ((drop= drop_it++))
{
if (!drop->drop_if_exists)
continue;
remove_drop= TRUE;
if (drop->type == Alter_drop::COLUMN)
{
/*
If there is NO field with that name in the table,
remove the 'drop' from the list.
*/
for (f_ptr=table->field; *f_ptr; f_ptr++)
{
if (my_strcasecmp(system_charset_info,
drop->name, (*f_ptr)->field_name) == 0)
{
remove_drop= FALSE;
break;
}
}
}
else /* Alter_drop::KEY */
{
uint n_key;
for (n_key=0; n_key < table->s->keys; n_key++)
{
if (my_strcasecmp(system_charset_info,
drop->name, table->key_info[n_key].name) == 0)
{
remove_drop= FALSE;
break;
}
}
}
if (remove_drop)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_CANT_DROP_FIELD_OR_KEY, ER(ER_CANT_DROP_FIELD_OR_KEY),
drop->name);
drop_it.remove();
if (alter_info->drop_list.is_empty())
alter_info->flags&= ~(ALTER_DROP_COLUMN | ALTER_DROP_INDEX);
}
}
}
/* ALTER TABLE ADD KEY IF NOT EXISTS */
/* ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS */
{
Key *key;
List_iterator<Key> key_it(alter_info->key_list);
uint n_key;
while ((key=key_it++))
{
if (!key->create_if_not_exists)
continue;
for (n_key=0; n_key < table->s->keys; n_key++)
{
if (my_strcasecmp(system_charset_info,
key->name.str, table->key_info[n_key].name) == 0)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DUP_KEYNAME, ER(ER_DUP_KEYNAME), key->name.str);
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_ADD_INDEX;
break;
}
}
}
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *tab_part_info= table->part_info;
if (tab_part_info && thd->lex->check_exists)
{
/* ALTER TABLE ADD PARTITION IF NOT EXISTS */
if (alter_info->flags & ALTER_ADD_PARTITION)
{
partition_info *alt_part_info= thd->lex->part_info;
if (alt_part_info)
{
List_iterator<partition_element> new_part_it(alt_part_info->partitions);
partition_element *pe;
while ((pe= new_part_it++))
{
if (!tab_part_info->has_unique_name(pe))
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SAME_NAME_PARTITION, ER(ER_SAME_NAME_PARTITION),
pe->partition_name);
alter_info->flags&= ~ALTER_ADD_PARTITION;
thd->lex->part_info= NULL;
break;
}
}
}
}
/* ALTER TABLE DROP PARTITION IF EXISTS */
if (alter_info->flags & ALTER_DROP_PARTITION)
{
List_iterator<char> names_it(alter_info->partition_names);
char *name;
while ((name= names_it++))
{
List_iterator<partition_element> part_it(tab_part_info->partitions);
partition_element *part_elem;
while ((part_elem= part_it++))
{
if (my_strcasecmp(system_charset_info,
part_elem->partition_name, name) == 0)
break;
}
if (!part_elem)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DROP_PARTITION_NON_EXISTENT,
ER(ER_DROP_PARTITION_NON_EXISTENT), "DROP");
names_it.remove();
}
}
if (alter_info->partition_names.elements == 0)
alter_info->flags&= ~ALTER_DROP_PARTITION;
}
}
#endif /*WITH_PARTITION_STORAGE_ENGINE*/
/* Clear the ALTER_FOREIGN_KEY flag if nothing other than that set. */
if (alter_info->flags == ALTER_FOREIGN_KEY)
alter_info->flags= 0;
DBUG_VOID_RETURN;
}
/*
SYNOPSIS
mysql_compare_tables()
@ -5873,7 +6113,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key= new Key(key_type, key_name, strlen(key_name),
&key_create_info,
test(key_info->flags & HA_GENERATED_KEY),
key_parts, key_info->option_list);
key_parts, key_info->option_list, FALSE);
new_key_list.push_back(key);
}
}
@ -6386,6 +6626,17 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(error);
}
handle_if_exists_options(thd, table, alter_info);
/* Look if we have to do anything at all. */
/* Normally ALTER can become NOOP only after handling */
/* the IF (NOT) EXISTS options. */
if (alter_info->flags == 0)
{
copied= deleted= 0;
goto end_temporary;
}
/* We have to do full alter table. */
#ifdef WITH_PARTITION_STORAGE_ENGINE