diff --git a/include/my_base.h b/include/my_base.h index c688591e1d53a4a2a59b4800ece011e2eb7a5034..5ea3795f7156c3138a39ba026f411f6ec6092e01 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -343,8 +343,9 @@ enum ha_base_keytype { #define HA_ERR_NO_CONNECTION 157 /* Could not connect to storage engine */ #define HA_ERR_NULL_IN_SPATIAL 158 /* NULLs are not supported in spatial index */ #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ +#define HA_ERR_NO_PARTITION_FOUND 160 /* There's no partition in table for given value */ -#define HA_ERR_LAST 159 /*Copy last error nr.*/ +#define HA_ERR_LAST 160 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index f0500c639a310983f5be081f740370ba6d5d5b7f..58f026816822d1799481645ebffd285d2010fa03 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -114,3 +114,37 @@ CREATE TABLE `t1` ( SELECT * FROM t1; id drop table t1; +create table t1 +(a int) +partition by range (a) +( partition p0 values less than(10), +partition p1 values less than (20), +partition p2 values less than maxvalue); +alter table t1 reorganise partition p2 into (partition p2 values less than (30)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (20) ENGINE = MyISAM, PARTITION p2 VALUES LESS THAN (30) ENGINE = MyISAM) +drop table t1; +CREATE TABLE t1 (a int, b int) +PARTITION BY RANGE (a) +(PARTITION x0 VALUES LESS THAN (2), +PARTITION x1 VALUES LESS THAN (4), +PARTITION x2 VALUES LESS THAN (6), +PARTITION x3 VALUES LESS THAN (8), +PARTITION x4 VALUES LESS THAN (10), +PARTITION x5 VALUES LESS THAN (12), +PARTITION x6 VALUES LESS THAN (14), +PARTITION x7 VALUES LESS THAN (16), +PARTITION x8 VALUES LESS THAN (18), +PARTITION x9 VALUES LESS THAN (20)); +ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO +(PARTITION x1 VALUES LESS THAN (6)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) default NULL, + `b` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) (PARTITION x1 VALUES LESS THAN (6) ENGINE = MyISAM, PARTITION x3 VALUES LESS THAN (8) ENGINE = MyISAM, PARTITION x4 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION x5 VALUES LESS THAN (12) ENGINE = MyISAM, PARTITION x6 VALUES LESS THAN (14) ENGINE = MyISAM, PARTITION x7 VALUES LESS THAN (16) ENGINE = MyISAM, PARTITION x8 VALUES LESS THAN (18) ENGINE = MyISAM, PARTITION x9 VALUES LESS THAN (20) ENGINE = MyISAM) +drop table t1; diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 58c42888ae74811e09140021e3d4c602c69efa50..90faa3b20b86cf7c360ca84213d27e51c0854dd0 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -544,3 +544,8 @@ partitions 2 partition x2 values in (5)); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '4, partition x2 values in (5))' at line 8 +CREATE TABLE t1(a int) +PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5)); +insert into t1 values (10); +ERROR HY000: Table has no partition for value 10 +drop table t1; diff --git a/mysql-test/r/partition_list.result b/mysql-test/r/partition_list.result index 23185e8aabf725bc23a2900be514fee99fc3c20c..21c23fd68ea48c48105a64a4712f7cd11dac0fa4 100644 --- a/mysql-test/r/partition_list.result +++ b/mysql-test/r/partition_list.result @@ -9,16 +9,16 @@ partitions 2 partition x234 values in (4,7,8)); INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (2,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 2 INSERT into t1 VALUES (3,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 3 INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); INSERT into t1 VALUES (6,1,1); INSERT into t1 VALUES (7,1,1); INSERT into t1 VALUES (8,1,1); INSERT into t1 VALUES (9,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 9 INSERT into t1 VALUES (1,2,1); INSERT into t1 VALUES (1,3,1); INSERT into t1 VALUES (1,4,1); @@ -137,7 +137,7 @@ a b c 7 4 1 INSERT into t1 VALUES (6,2,1); INSERT into t1 VALUES (2,2,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 2 drop table t1; CREATE TABLE t1 ( a int not null, @@ -156,7 +156,7 @@ subpartition x22 nodegroup 1) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (7,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 7 UPDATE t1 SET a=5 WHERE a=1; SELECT * from t1; a b c diff --git a/mysql-test/r/partition_mgm_err.result b/mysql-test/r/partition_mgm_err.result index ca56dc4466624a41d466ac124365bf4a6036adbb..01709e726bd98e4754e5135aff7728f653a9fd59 100644 --- a/mysql-test/r/partition_mgm_err.result +++ b/mysql-test/r/partition_mgm_err.result @@ -26,7 +26,7 @@ ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 INTO (PARTITION x11 VALUES LESS THAN (22)); ERROR HY000: More partitions to reorganise than there are partitions ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO -(PARTITION x1 VALUES LESS THAN (6)); +(PARTITION x3 VALUES LESS THAN (6)); ERROR HY000: All partitions must have unique names in the table ALTER TABLE t1 REORGANISE PARTITION x0, x2 INTO (PARTITION x11 VALUES LESS THAN (2)); diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index f8b4f1b054b64a4be2c29d912fbeb7b2ab6f516f..072c51cc83940898dfc36d2f374b58acc49334c3 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -94,7 +94,7 @@ INSERT into t1 values (1, 1, 1); INSERT into t1 values (6, 1, 1); INSERT into t1 values (10, 1, 1); INSERT into t1 values (15, 1, 1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 15 select * from t1; a b c 1 1 1 @@ -206,7 +206,7 @@ subpartition x22 engine myisam nodegroup 1) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 5 SELECT * from t1; a b c 1 1 1 @@ -243,7 +243,7 @@ subpartition x22 tablespace t2 engine myisam) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 5 SELECT * from t1; a b c 1 1 1 @@ -280,7 +280,7 @@ subpartition x22 tablespace t2) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 5 SELECT * from t1; a b c 1 1 1 @@ -317,7 +317,7 @@ subpartition x22 engine myisam) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); -ERROR HY000: Got error 1 from storage engine +ERROR HY000: Table has no partition for value 5 SELECT * from t1; a b c 1 1 1 diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 8f20f7be5365a85feea5e94cee4fd331948cf9cf..8b1c3f5807187cbb9608ca4f72ab8c8a6aa2249c 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -172,3 +172,34 @@ SELECT * FROM t1; drop table t1; +# +# BUG 15221 (Cannot reorganize with the same name) +# +create table t1 +(a int) +partition by range (a) + ( partition p0 values less than(10), + partition p1 values less than (20), + partition p2 values less than maxvalue); + +alter table t1 reorganise partition p2 into (partition p2 values less than (30)); +show create table t1; +drop table t1; + +CREATE TABLE t1 (a int, b int) +PARTITION BY RANGE (a) +(PARTITION x0 VALUES LESS THAN (2), + PARTITION x1 VALUES LESS THAN (4), + PARTITION x2 VALUES LESS THAN (6), + PARTITION x3 VALUES LESS THAN (8), + PARTITION x4 VALUES LESS THAN (10), + PARTITION x5 VALUES LESS THAN (12), + PARTITION x6 VALUES LESS THAN (14), + PARTITION x7 VALUES LESS THAN (16), + PARTITION x8 VALUES LESS THAN (18), + PARTITION x9 VALUES LESS THAN (20)); + +ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO +(PARTITION x1 VALUES LESS THAN (6)); +show create table t1; +drop table t1; diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index b4851dcf8c000fbff79a00a9833a032a94da55b1..ea12bbc52077209cb88c027595044591f24c3a0a 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -727,3 +727,11 @@ partitions 2 (partition x1 values in 4, partition x2 values in (5)); +# +# No partition for the given value +# +CREATE TABLE t1(a int) + PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5)); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +insert into t1 values (10); +drop table t1; diff --git a/mysql-test/t/partition_list.test b/mysql-test/t/partition_list.test index cb8d06a11ed9ae5aa16235292b5e6b7edda07803..af99321dcb22a2b75b94a161d3ac209d2609793f 100644 --- a/mysql-test/t/partition_list.test +++ b/mysql-test/t/partition_list.test @@ -22,16 +22,16 @@ partitions 2 partition x234 values in (4,7,8)); INSERT into t1 VALUES (1,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (2,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (3,1,1); INSERT into t1 VALUES (4,1,1); INSERT into t1 VALUES (5,1,1); INSERT into t1 VALUES (6,1,1); INSERT into t1 VALUES (7,1,1); INSERT into t1 VALUES (8,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (9,1,1); INSERT into t1 VALUES (1,2,1); INSERT into t1 VALUES (1,3,1); @@ -64,7 +64,7 @@ partitions 2 partition x234 values in (4,7,8)); SELECT * from t1; INSERT into t1 VALUES (6,2,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (2,2,1); drop table t1; @@ -89,7 +89,7 @@ subpartition by hash (a+b) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (7,1,1); UPDATE t1 SET a=5 WHERE a=1; SELECT * from t1; diff --git a/mysql-test/t/partition_mgm_err.test b/mysql-test/t/partition_mgm_err.test index 1d9d8a79f3da005b77d42401f66bac836a02806a..92848fc135e2ba12388555da160d50aae6e03f72 100644 --- a/mysql-test/t/partition_mgm_err.test +++ b/mysql-test/t/partition_mgm_err.test @@ -43,7 +43,7 @@ ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 INTO --error ER_SAME_NAME_PARTITION ALTER TABLE t1 REORGANISE PARTITION x0,x1,x2 INTO -(PARTITION x1 VALUES LESS THAN (6)); +(PARTITION x3 VALUES LESS THAN (6)); --error ER_CONSECUTIVE_REORG_PARTITIONS ALTER TABLE t1 REORGANISE PARTITION x0, x2 INTO diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 08cc841b12ef7565166e5eb23d0da4e55333f50b..9a81914ed2d7c8f51ab56db923ff979d9c22cb98 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -97,7 +97,7 @@ partitions 3 INSERT into t1 values (1, 1, 1); INSERT into t1 values (6, 1, 1); INSERT into t1 values (10, 1, 1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 values (15, 1, 1); select * from t1; @@ -219,7 +219,7 @@ subpartition by hash (a+b) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (5,1,1); SELECT * from t1; @@ -260,7 +260,7 @@ subpartition by hash (a+b) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (5,1,1); SELECT * from t1; @@ -301,7 +301,7 @@ subpartition by hash (a+b) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (5,1,1); SELECT * from t1; @@ -342,7 +342,7 @@ subpartition by hash (a+b) INSERT into t1 VALUES (1,1,1); INSERT into t1 VALUES (4,1,1); ---error 1030 +--error ER_NO_PARTITION_FOR_GIVEN_VALUE INSERT into t1 VALUES (5,1,1); SELECT * from t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 650830832cb3d447f631d0f91fe8bd12abc4718b..b0b4ac3fdcdf7b61a3989660525307c018bfcd41 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1174,7 +1174,7 @@ int ha_partition::write_row(byte * buf) } #endif if (unlikely(error)) - DBUG_RETURN(error); + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); m_last_part= part_id; DBUG_PRINT("info", ("Insert in partition %d", part_id)); DBUG_RETURN(m_file[part_id]->write_row(buf)); @@ -2973,7 +2973,11 @@ void ha_partition::print_error(int error, myf errflag) DBUG_ENTER("ha_partition::print_error"); /* Should probably look for my own errors first */ /* monty: needs to be called for the last used partition ! */ - m_file[0]->print_error(error, errflag); + if (error == HA_ERR_NO_PARTITION_FOUND) + my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), + m_part_info->part_expr->val_int()); + else + m_file[0]->print_error(error, errflag); DBUG_VOID_RETURN; } diff --git a/sql/handler.h b/sql/handler.h index b4b90cbfaa84169c4fdafad7edaac158df7af3c4..5674698487c351730305c1efce8566087d572c29 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -717,6 +717,9 @@ typedef struct st_ha_check_opt bool is_partition_in_list(char *part_name, List<char> list_part_names); bool is_partitions_in_table(partition_info *new_part_info, partition_info *old_part_info); +bool check_reorganise_list(partition_info *new_part_info, + partition_info *old_part_info, + List<char> list_part_names); bool set_up_defaults_for_partitioning(partition_info *part_info, handler *file, ulonglong max_rows, diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d6be040586577cf33969bfe6a96ed0fa94b0c36d..35b6b17efa477a571f5687d4e233c88c4e4431bc 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5725,3 +5725,5 @@ ER_PLUGIN_IS_NOT_LOADED eng "Plugin '%-.64s' is not loaded" ER_WRONG_VALUE eng "Incorrect %-.32s value: '%-.128s'" +ER_NO_PARTITION_FOR_GIVEN_VALUE + eng "Table has no partition for value %d" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index dd4f2d9246abba0ffb8f73afffabe4586e0788c2..8571e39d9b8b843b4ddbc15d4ec5731405e58a74 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -189,6 +189,61 @@ bool is_partitions_in_table(partition_info *new_part_info, } +/* + Check that the reorganized table will not have duplicate partitions. + + SYNOPSIS + check_reorganise_list() + new_part_info New partition info + old_part_info Old partition info + list_part_names The list of partition names that will go away and can be reused in the + new table. + + RETURN VALUES + TRUE Inacceptable name conflict detected. + FALSE New names are OK. + + DESCRIPTION + Can handle that the 'new_part_info' and 'old_part_info' the same + in which case it checks that the list of names in the partitions + doesn't contain any duplicated names. +*/ + +bool check_reorganise_list(partition_info *new_part_info, + partition_info *old_part_info, + List<char> list_part_names) +{ + uint new_count, old_count; + uint no_new_parts= new_part_info->partitions.elements; + uint no_old_parts= old_part_info->partitions.elements; + List_iterator<partition_element> new_parts_it(new_part_info->partitions); + bool same_part_info= (new_part_info == old_part_info); + DBUG_ENTER("check_reorganise_list"); + + new_count= 0; + do + { + List_iterator<partition_element> old_parts_it(old_part_info->partitions); + char *new_name= (new_parts_it++)->partition_name; + new_count++; + old_count= 0; + do + { + char *old_name= (old_parts_it++)->partition_name; + old_count++; + if (same_part_info && old_count == new_count) + break; + if (!(my_strcasecmp(system_charset_info, old_name, new_name))) + { + if (!is_partition_in_list(old_name, list_part_names)) + DBUG_RETURN(TRUE); + } + } while (old_count < no_old_parts); + } while (new_count < no_new_parts); + DBUG_RETURN(FALSE); +} + + /* A useful routine used by update_row for partition handlers to calculate the partition ids of the old and the new record. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 275cf847a99b990ad099a1f4f59c745769af93a6..a74a550679f697d92023a76d0a2a309231669ad1 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3832,7 +3832,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "REORGANISE"); DBUG_RETURN(TRUE); } - if (is_partitions_in_table(alt_part_info, tab_part_info)) + if (check_reorganise_list(alt_part_info, tab_part_info, + alter_info->partition_names)) { my_error(ER_SAME_NAME_PARTITION, MYF(0)); DBUG_RETURN(TRUE); @@ -3901,6 +3902,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } } partition_changed= TRUE; + tab_part_info->no_parts= tab_part_info->partitions.elements; create_info->db_type= DB_TYPE_PARTITION_DB; thd->lex->part_info= tab_part_info; if (alter_info->flags == ALTER_ADD_PARTITION ||