diff --git a/mysql-test/r/partition_alter.result b/mysql-test/r/partition_alter.result index 6aa0039c8d2..e42604ba056 100644 --- a/mysql-test/r/partition_alter.result +++ b/mysql-test/r/partition_alter.result @@ -120,3 +120,10 @@ t1 CREATE TABLE `t1` ( PARTITION `p02` ENGINE = MyISAM, PARTITION `p03` ENGINE = MyISAM) drop table t1; +create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +lock table t1 write; +alter table t1 add partition (partition p1); +ERROR HY000: Duplicate partition name p1 +alter table t1 add partition (partition p1); +ERROR HY000: Duplicate partition name p1 +drop table t1; diff --git a/mysql-test/t/partition_alter.test b/mysql-test/t/partition_alter.test index ce6672c4b9d..62a3e1c0777 100644 --- a/mysql-test/t/partition_alter.test +++ b/mysql-test/t/partition_alter.test @@ -114,3 +114,14 @@ insert into t1 values(0, 1, 1, NULL, now(), now()); alter online table t1 delay_key_write=1; show create table t1; drop table t1; + +# +# MDEV-14817 Server crashes in prep_alter_part_table() after table lock and multiple add partition +# +create or replace table t1 (x int) partition by hash (x) (partition p1, partition p2); +lock table t1 write; +--error ER_SAME_NAME_PARTITION +alter table t1 add partition (partition p1); +--error ER_SAME_NAME_PARTITION +alter table t1 add partition (partition p1); +drop table t1; diff --git a/sql/sql_class.h b/sql/sql_class.h index b56729737de..fddd736fc56 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1797,8 +1797,9 @@ private: class Locked_tables_list { -private: +public: MEM_ROOT m_locked_tables_root; +private: TABLE_LIST *m_locked_tables; TABLE_LIST **m_locked_tables_last; /** An auxiliary array used only in reopen_tables(). */ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 879a29f4e42..f5fd7c891d8 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4573,6 +4573,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */ DBUG_ASSERT(!(alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION)); + partition_info *saved_part_info= NULL; + if (alter_info->flags & (Alter_info::ALTER_ADD_PARTITION | Alter_info::ALTER_DROP_PARTITION | @@ -4778,6 +4780,16 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, } if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION) { + if (*fast_alter_table && thd->locked_tables_mode) + { + MEM_ROOT *old_root= thd->mem_root; + thd->mem_root= &thd->locked_tables_list.m_locked_tables_root; + saved_part_info= tab_part_info->get_clone(thd); + thd->mem_root= old_root; + saved_part_info->read_partitions= tab_part_info->read_partitions; + saved_part_info->lock_partitions= tab_part_info->lock_partitions; + saved_part_info->bitmaps_are_initialized= tab_part_info->bitmaps_are_initialized; + } /* We start by moving the new partitions to the list of temporary partitions. We will then check that the new partitions fit in the @@ -5472,7 +5484,7 @@ the generated partition syntax in a correct manner. goto err; } } - } + } // ADD, DROP, COALESCE, REORGANIZE, TABLE_REORG, REBUILD else { /* @@ -5638,6 +5650,8 @@ the generated partition syntax in a correct manner. DBUG_RETURN(FALSE); err: *fast_alter_table= false; + if (saved_part_info) + table->part_info= saved_part_info; DBUG_RETURN(TRUE); }