diff --git a/mysql-test/r/ndb_partition_key.result b/mysql-test/r/ndb_partition_key.result index 87b019c83e2..8225fca7a54 100644 --- a/mysql-test/r/ndb_partition_key.result +++ b/mysql-test/r/ndb_partition_key.result @@ -165,3 +165,21 @@ ENGINE=NDB PARTITION BY KEY(c3) PARTITIONS 5; ALTER TABLE t1 COALESCE PARTITION 4; DROP TABLE t1; +CREATE TABLE t1 ( +c1 MEDIUMINT NOT NULL AUTO_INCREMENT, +c2 TEXT NOT NULL, +c3 INT NOT NULL, +PRIMARY KEY(c1,c3)) +ENGINE=NDB +PARTITION BY KEY(c3) PARTITIONS 5; +ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1; +DROP TABLE t1; +CREATE TABLE t1 ( +c1 MEDIUMINT NOT NULL AUTO_INCREMENT, +c2 TEXT NOT NULL, +c3 INT NOT NULL, +PRIMARY KEY(c1,c3)) +ENGINE=NDB +PARTITION BY KEY(c3); +ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1; +DROP TABLE t1; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 2564943293f..cf2e52bb0e1 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -19,7 +19,7 @@ ndb_autodiscover2 : Needs to be fixed w.r.t binlog ndb_binlog_ddl_multi : Bug #18490 cluster: binlog events lost on remote mysqld (asynchronous) #ndb_binlog_multi : Results are not deterministic, Tomas will fix ndb_load : Bug#17233 -#partition_03ndb : Bug#16385 +partition_03ndb : Bug#16385 ps_7ndb : dbug assert in RBR mode when executing test suite #rpl_bit_npk : Bug#13418 #rpl_ddl : Bug#15963 SBR does not show "Definer" correctly diff --git a/mysql-test/t/ndb_partition_key.test b/mysql-test/t/ndb_partition_key.test index d43dc7e49e4..87933671529 100644 --- a/mysql-test/t/ndb_partition_key.test +++ b/mysql-test/t/ndb_partition_key.test @@ -153,3 +153,28 @@ b'0', ALTER TABLE t1 COALESCE PARTITION 4; DROP TABLE t1; + +# +# BUG 16806: ALTER TABLE fails +# +CREATE TABLE t1 ( + c1 MEDIUMINT NOT NULL AUTO_INCREMENT, + c2 TEXT NOT NULL, + c3 INT NOT NULL, + PRIMARY KEY(c1,c3)) + ENGINE=NDB + PARTITION BY KEY(c3) PARTITIONS 5; + +ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1; +DROP TABLE t1; + +CREATE TABLE t1 ( + c1 MEDIUMINT NOT NULL AUTO_INCREMENT, + c2 TEXT NOT NULL, + c3 INT NOT NULL, + PRIMARY KEY(c1,c3)) + ENGINE=NDB + PARTITION BY KEY(c3); + +ALTER TABLE t1 ADD COLUMN c4 INT AFTER c1; +DROP TABLE t1; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 62c48ba37dc..682c74dc31e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -199,13 +199,15 @@ bool is_name_in_list(char *name, */ bool partition_default_handling(TABLE *table, partition_info *part_info, + bool is_create_table_ind, const char *normalized_path) { DBUG_ENTER("partition_default_handling"); if (part_info->use_default_no_partitions) { - if (table->file->get_no_parts(normalized_path, &part_info->no_parts)) + if (!is_create_table_ind && + table->file->get_no_parts(normalized_path, &part_info->no_parts)) { DBUG_RETURN(TRUE); } @@ -214,7 +216,8 @@ bool partition_default_handling(TABLE *table, partition_info *part_info, part_info->use_default_no_subpartitions) { uint no_parts; - if (table->file->get_no_parts(normalized_path, &no_parts)) + if (!is_create_table_ind && + (table->file->get_no_parts(normalized_path, &no_parts))) { DBUG_RETURN(TRUE); } @@ -1737,9 +1740,11 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, db_name= &db_name_string[home_dir_length]; tables.db= db_name; - if (!is_create_table_ind) + if (!is_create_table_ind || + thd->lex->sql_command != SQLCOM_CREATE_TABLE) { if (partition_default_handling(table, part_info, + is_create_table_ind, table->s->normalized_path.str)) { DBUG_RETURN(TRUE); @@ -3742,7 +3747,7 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf, DBUG_PRINT("info", ("default engine = %d, default_db_type = %d", ha_legacy_type(part_info->default_engine_type), ha_legacy_type(default_db_type))); - if (is_create_table_ind) + if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE) { if (old_lex->like_name) { @@ -3756,14 +3761,32 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf, char *src_table= table_ident->table.str; char buf[FN_REFLEN]; build_table_filename(buf, sizeof(buf), src_db, src_table, ""); - if (partition_default_handling(table, part_info, buf)) + if (partition_default_handling(table, part_info, + FALSE, buf)) { result= TRUE; goto end; } } else + { + /* + When we come here we are doing a create table. In this case we + have already done some preparatory work on the old part_info + object. We don't really need this new partition_info object. + Thus we go back to the old partition info object. + We need to free any memory objects allocated on item_free_list + by the parser since we are keeping the old info from the first + parser call in CREATE TABLE. + We'll ensure that this object isn't put into table cache also + just to ensure we don't get into strange situations with the + item objects. + */ + free_items(thd->free_list); part_info= thd->work_part_info; + thd->free_list= NULL; + table->s->version= 0UL; + } } table->part_info= part_info; table->file->set_part_info(part_info); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f63e0cbbcac..32184be649c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2130,15 +2130,6 @@ bool mysql_create_table_internal(THD *thd, goto err; part_info->part_info_string= part_syntax_buf; part_info->part_info_len= syntax_len; - if (create_info->db_type != engine_type) - { - delete file; - if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, engine_type))) - { - mem_alloc_error(sizeof(handler)); - DBUG_RETURN(TRUE); - } - } if ((!(engine_type->partition_flags && engine_type->partition_flags() & HA_CAN_PARTITION)) || create_info->db_type == &partition_hton) @@ -2155,6 +2146,41 @@ bool mysql_create_table_internal(THD *thd, { DBUG_RETURN(TRUE); } + /* + If we have default number of partitions or subpartitions we + might require to set-up the part_info object such that it + creates a proper .par file. The current part_info object is + only used to create the frm-file and .par-file. + */ + if (part_info->use_default_no_partitions && + part_info->no_parts && + (int)part_info->no_parts != file->get_default_no_partitions(0ULL)) + { + uint i; + List_iterator part_it(part_info->partitions); + part_it++; + DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE); + for (i= 1; i < part_info->partitions.elements; i++) + (part_it++)->part_state= PART_TO_BE_DROPPED; + } + else if (part_info->is_sub_partitioned() && + part_info->use_default_no_subpartitions && + part_info->no_subparts && + (int)part_info->no_subparts != + file->get_default_no_partitions(0ULL)) + { + DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE); + part_info->no_subparts= file->get_default_no_partitions(0ULL); + } + } + else if (create_info->db_type != engine_type) + { + delete file; + if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, engine_type))) + { + mem_alloc_error(sizeof(handler)); + DBUG_RETURN(TRUE); + } } } #endif