From 43179555d90d1aee70d196e918e981f70168eb8d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Jul 2006 12:57:23 -0400 Subject: [PATCH 1/5] BUG#20770: DATA DIRECTORY and INDEX DIRECTORY error when ALTER TABLE ADD/DROP/REORGANIZE partition Also some error in handling options for subpartitions. mysql-test/r/partition.result: New test cases mysql-test/t/partition.test: New test cases sql/ha_partition.cc: Added partition_element to prepare_new_partition so that we can properly set-up table before creating partitions. sql/ha_partition.h: Added partition_element to prepare_new_partition so that we can properly set-up table before creating partitions. sql/sql_yacc.yy: Ensure that subpartitions always inherit options from the partition they belong to. They can change it afterwards but will use the options as set on partition level if set at that level. --- mysql-test/r/partition.result | 39 +++++++++++++++++++++++++++++++ mysql-test/t/partition.test | 43 +++++++++++++++++++++++++++++++++++ sql/ha_partition.cc | 23 ++++++++++++------- sql/ha_partition.h | 6 +++-- sql/sql_yacc.yy | 9 ++++---- 5 files changed, 106 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 8bb895386bf..26969d1ad5d 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1082,4 +1082,43 @@ a 2 1 drop table t1; +create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart00, SUBPARTITION subpart01)); +t1#P#p0#SP#subpart00.MYD +t1#P#p0#SP#subpart00.MYI +t1#P#p0#SP#subpart01.MYD +t1#P#p0#SP#subpart01.MYI +t1.frm +t1.par +t1#P#p0#SP#subpart00.MYD +t1#P#p0#SP#subpart01.MYD +t1#P#p0#SP#subpart00.MYI +t1#P#p0#SP#subpart01.MYI +ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart10, SUBPARTITION subpart11), +partition p2 VALUES LESS THAN (2) DATA DIRECTORY = 'hello/master-data/tmpdata' INDEX DIRECTORY = 'hello/master-data/tmpinx' +(SUBPARTITION subpart20, SUBPARTITION subpart21)); +t1#P#p1#SP#subpart10.MYD +t1#P#p1#SP#subpart10.MYI +t1#P#p1#SP#subpart11.MYD +t1#P#p1#SP#subpart11.MYI +t1#P#p2#SP#subpart20.MYD +t1#P#p2#SP#subpart20.MYI +t1#P#p2#SP#subpart21.MYD +t1#P#p2#SP#subpart21.MYI +t1.frm +t1.par +t1#P#p1#SP#subpart10.MYD +t1#P#p1#SP#subpart11.MYD +t1#P#p2#SP#subpart20.MYD +t1#P#p2#SP#subpart21.MYD +t1#P#p1#SP#subpart10.MYI +t1#P#p1#SP#subpart11.MYI +t1#P#p2#SP#subpart20.MYI +t1#P#p2#SP#subpart21.MYI +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 04519800ff6..1c606c47183 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1261,4 +1261,47 @@ insert into t1 values (1),(2); select * from t1 ORDER BY a DESC; drop table t1; +# +# Bug 20770 Partitions: DATA DIRECTORY clause change in reorganize +# doesn't remove old directory +# +--disable_query_log +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpdata || true +eval SET @data_dir = 'DATA DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpdata'''; +let $data_directory = `select @data_dir`; + +--exec mkdir $MYSQLTEST_VARDIR/master-data/tmpinx || true +eval SET @inx_dir = 'INDEX DIRECTORY = ''$MYSQLTEST_VARDIR/master-data/tmpinx'''; +let $inx_directory = `select @inx_dir`; +--enable_query_log + +--replace_result $MYSQLTEST_VARDIR "hello" +eval create table t1 (a int) engine myisam +partition by range (a) +subpartition by hash (a) +(partition p0 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart00, SUBPARTITION subpart01)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true +--replace_result $MYSQLTEST_VARDIR "hello" + +eval ALTER TABLE t1 REORGANIZE PARTITION p0 INTO +(partition p1 VALUES LESS THAN (1) $data_directory $inx_directory + (SUBPARTITION subpart10, SUBPARTITION subpart11), + partition p2 VALUES LESS THAN (2) $data_directory $inx_directory + (SUBPARTITION subpart20, SUBPARTITION subpart21)); + +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/test || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpdata || true +--replace_result $MYSQLTEST_VARDIR "hello" +--exec ls $MYSQLTEST_VARDIR/master-data/tmpinx || true + +drop table t1; --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..85b02553be4 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1125,13 +1125,15 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, int ha_partition::prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name) + handler *file, const char *part_name, + partition_element *p_elem) { int error; bool create_flag= FALSE; bool open_flag= FALSE; DBUG_ENTER("prepare_new_partition"); + set_up_table_before_create(table, part_name, create_info, 0, p_elem); if ((error= file->create(part_name, table, create_info))) goto error; create_flag= TRUE; @@ -1420,7 +1422,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add subpartition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[part], - (const char *)part_name_buff))) + (const char *)part_name_buff, + sub_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1436,7 +1439,8 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], - (const char *)part_name_buff))) + (const char *)part_name_buff, + part_elem))) { cleanup_new_partition(part_count); DBUG_RETURN(error); @@ -1648,7 +1652,7 @@ uint ha_partition::del_ren_cre_table(const char *from, error= (*file)->delete_table((const char*) from_buff); else { - set_up_table_before_create(table_arg, from_buff, create_info, i); + set_up_table_before_create(table_arg, from_buff, create_info, i, NULL); error= (*file)->create(from_buff, table_arg, create_info); } name_buffer_ptr= strend(name_buffer_ptr) + 1; @@ -1724,12 +1728,15 @@ partition_element *ha_partition::find_partition_element(uint part_id) void ha_partition::set_up_table_before_create(TABLE *table, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id) + uint part_id, + partition_element *part_elem) { - partition_element *part_elem= find_partition_element(part_id); - if (!part_elem) - return; // Fatal error + { + part_elem= find_partition_element(part_id); + if (!part_elem) + return; // Fatal error + } table->s->max_rows= part_elem->part_max_rows; table->s->min_rows= part_elem->part_min_rows; const char *partition_name= strrchr(partition_name_with_path, FN_LIBCHAR); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..cbf87ae3a92 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -202,7 +202,8 @@ private: int copy_partitions(ulonglong *copied, ulonglong *deleted); void cleanup_new_partition(uint part_count); int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info, - handler *file, const char *part_name); + handler *file, const char *part_name, + partition_element *p_elem); /* delete_table, rename_table and create uses very similar logic which is packed into this routine. @@ -222,7 +223,8 @@ private: void set_up_table_before_create(TABLE *table_arg, const char *partition_name_with_path, HA_CREATE_INFO *info, - uint part_id); + uint part_id, + partition_element *p_elem); partition_element *find_partition_element(uint part_id); public: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0632e2298cd..0001676aab4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3716,14 +3716,15 @@ sub_part_definition: { LEX *lex= Lex; partition_info *part_info= lex->part_info; - partition_element *p_elem= new partition_element(); - if (!p_elem || - part_info->current_partition->subpartitions.push_back(p_elem)) + partition_element *curr_part= part_info->current_partition; + partition_element *sub_p_elem= new partition_element(curr_part); + if (!sub_p_elem || + curr_part->subpartitions.push_back(sub_p_elem)) { mem_alloc_error(sizeof(partition_element)); YYABORT; } - part_info->curr_part_elem= p_elem; + part_info->curr_part_elem= sub_p_elem; part_info->use_default_subpartitions= FALSE; part_info->use_default_no_subpartitions= FALSE; part_info->count_curr_subparts++; From f481a6a8943670987db4a48c006b3b53a133b2df Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Jul 2006 16:06:51 -0400 Subject: [PATCH 2/5] BUG#20770: Added some more test cases mysql-test/r/partition_range.result: New test case mysql-test/t/partition_range.test: New test case sql/partition_info.cc: No changes --- mysql-test/r/partition_range.result | 112 ++++++++++++++++++++++++++++ mysql-test/t/partition_range.test | 87 +++++++++++++++++++++ 2 files changed, 199 insertions(+) diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index 3cbb517053a..9123c894f32 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -519,3 +519,115 @@ partition p3 values less than (1998), partition p4 values less than (1999), partition p5 values less than (2000)); drop table t1; +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), +PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), +PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), +PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), +PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), +PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), +PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), +PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), +PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), +PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), +PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), +PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), +PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), +PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), +PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), +PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), +PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), +PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), +PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), +PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), +PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), +PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), +PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), +PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), +PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), +PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), +PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), +PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), +PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), +PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), +PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), +PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR +(a >= '2005-07-01' AND a <= '2005-09-30'); +a +2004-07-13 +2004-07-20 +2004-07-30 +2004-08-13 +2004-08-20 +2004-08-30 +2004-09-13 +2004-09-20 +2004-09-30 +2005-07-13 +2005-07-20 +2005-07-30 +2005-08-13 +2005-08-20 +2005-08-30 +2005-09-13 +2005-09-20 +2005-09-30 +EXPLAIN PARTITIONS SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR +(a >= '2005-07-01' AND a <= '2005-09-30'); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where +DROP TABLE t1; diff --git a/mysql-test/t/partition_range.test b/mysql-test/t/partition_range.test index 8e1e2e72e69..38142a9d485 100644 --- a/mysql-test/t/partition_range.test +++ b/mysql-test/t/partition_range.test @@ -555,3 +555,90 @@ reorganize partition p5 into drop table t1; +# +# New test cases for date based partitioning +# +CREATE TABLE t1 (a date) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION p3xx VALUES LESS THAN (TO_DAYS('2004-01-01')), + PARTITION p401 VALUES LESS THAN (TO_DAYS('2004-02-01')), + PARTITION p402 VALUES LESS THAN (TO_DAYS('2004-03-01')), + PARTITION p403 VALUES LESS THAN (TO_DAYS('2004-04-01')), + PARTITION p404 VALUES LESS THAN (TO_DAYS('2004-05-01')), + PARTITION p405 VALUES LESS THAN (TO_DAYS('2004-06-01')), + PARTITION p406 VALUES LESS THAN (TO_DAYS('2004-07-01')), + PARTITION p407 VALUES LESS THAN (TO_DAYS('2004-08-01')), + PARTITION p408 VALUES LESS THAN (TO_DAYS('2004-09-01')), + PARTITION p409 VALUES LESS THAN (TO_DAYS('2004-10-01')), + PARTITION p410 VALUES LESS THAN (TO_DAYS('2004-11-01')), + PARTITION p411 VALUES LESS THAN (TO_DAYS('2004-12-01')), + PARTITION p412 VALUES LESS THAN (TO_DAYS('2005-01-01')), + PARTITION p501 VALUES LESS THAN (TO_DAYS('2005-02-01')), + PARTITION p502 VALUES LESS THAN (TO_DAYS('2005-03-01')), + PARTITION p503 VALUES LESS THAN (TO_DAYS('2005-04-01')), + PARTITION p504 VALUES LESS THAN (TO_DAYS('2005-05-01')), + PARTITION p505 VALUES LESS THAN (TO_DAYS('2005-06-01')), + PARTITION p506 VALUES LESS THAN (TO_DAYS('2005-07-01')), + PARTITION p507 VALUES LESS THAN (TO_DAYS('2005-08-01')), + PARTITION p508 VALUES LESS THAN (TO_DAYS('2005-09-01')), + PARTITION p509 VALUES LESS THAN (TO_DAYS('2005-10-01')), + PARTITION p510 VALUES LESS THAN (TO_DAYS('2005-11-01')), + PARTITION p511 VALUES LESS THAN (TO_DAYS('2005-12-01')), + PARTITION p512 VALUES LESS THAN (TO_DAYS('2006-01-01')), + PARTITION p601 VALUES LESS THAN (TO_DAYS('2006-02-01')), + PARTITION p602 VALUES LESS THAN (TO_DAYS('2006-03-01')), + PARTITION p603 VALUES LESS THAN (TO_DAYS('2006-04-01')), + PARTITION p604 VALUES LESS THAN (TO_DAYS('2006-05-01')), + PARTITION p605 VALUES LESS THAN (TO_DAYS('2006-06-01')), + PARTITION p606 VALUES LESS THAN (TO_DAYS('2006-07-01')), + PARTITION p607 VALUES LESS THAN (TO_DAYS('2006-08-01'))); + +INSERT INTO t1 VALUES ('2003-01-13'),('2003-06-20'),('2003-08-30'); +INSERT INTO t1 VALUES ('2003-04-13'),('2003-07-20'),('2003-10-30'); +INSERT INTO t1 VALUES ('2003-05-13'),('2003-11-20'),('2003-12-30'); + +INSERT INTO t1 VALUES ('2004-01-13'),('2004-01-20'),('2004-01-30'); +INSERT INTO t1 VALUES ('2004-02-13'),('2004-02-20'),('2004-02-28'); +INSERT INTO t1 VALUES ('2004-03-13'),('2004-03-20'),('2004-03-30'); +INSERT INTO t1 VALUES ('2004-04-13'),('2004-04-20'),('2004-04-30'); +INSERT INTO t1 VALUES ('2004-05-13'),('2004-05-20'),('2004-05-30'); +INSERT INTO t1 VALUES ('2004-06-13'),('2004-06-20'),('2004-06-30'); +INSERT INTO t1 VALUES ('2004-07-13'),('2004-07-20'),('2004-07-30'); +INSERT INTO t1 VALUES ('2004-08-13'),('2004-08-20'),('2004-08-30'); +INSERT INTO t1 VALUES ('2004-09-13'),('2004-09-20'),('2004-09-30'); +INSERT INTO t1 VALUES ('2004-10-13'),('2004-10-20'),('2004-10-30'); +INSERT INTO t1 VALUES ('2004-11-13'),('2004-11-20'),('2004-11-30'); +INSERT INTO t1 VALUES ('2004-12-13'),('2004-12-20'),('2004-12-30'); + +INSERT INTO t1 VALUES ('2005-01-13'),('2005-01-20'),('2005-01-30'); +INSERT INTO t1 VALUES ('2005-02-13'),('2005-02-20'),('2005-02-28'); +INSERT INTO t1 VALUES ('2005-03-13'),('2005-03-20'),('2005-03-30'); +INSERT INTO t1 VALUES ('2005-04-13'),('2005-04-20'),('2005-04-30'); +INSERT INTO t1 VALUES ('2005-05-13'),('2005-05-20'),('2005-05-30'); +INSERT INTO t1 VALUES ('2005-06-13'),('2005-06-20'),('2005-06-30'); +INSERT INTO t1 VALUES ('2005-07-13'),('2005-07-20'),('2005-07-30'); +INSERT INTO t1 VALUES ('2005-08-13'),('2005-08-20'),('2005-08-30'); +INSERT INTO t1 VALUES ('2005-09-13'),('2005-09-20'),('2005-09-30'); +INSERT INTO t1 VALUES ('2005-10-13'),('2005-10-20'),('2005-10-30'); +INSERT INTO t1 VALUES ('2005-11-13'),('2005-11-20'),('2005-11-30'); +INSERT INTO t1 VALUES ('2005-12-13'),('2005-12-20'),('2005-12-30'); + +INSERT INTO t1 VALUES ('2006-01-13'),('2006-01-20'),('2006-01-30'); +INSERT INTO t1 VALUES ('2006-02-13'),('2006-02-20'),('2006-02-28'); +INSERT INTO t1 VALUES ('2006-03-13'),('2006-03-20'),('2006-03-30'); +INSERT INTO t1 VALUES ('2006-04-13'),('2006-04-20'),('2006-04-30'); +INSERT INTO t1 VALUES ('2006-05-13'),('2006-05-20'),('2006-05-30'); +INSERT INTO t1 VALUES ('2006-06-13'),('2006-06-20'),('2006-06-30'); +INSERT INTO t1 VALUES ('2006-07-13'),('2006-07-20'),('2006-07-30'); + +SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE a >= '2004-07-01' AND a <= '2004-09-30'; +SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR + (a >= '2005-07-01' AND a <= '2005-09-30'); +EXPLAIN PARTITIONS SELECT * from t1 +WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR + (a >= '2005-07-01' AND a <= '2005-09-30'); +DROP TABLE t1; From 907df8e3c8ae2133aa9ec4b7807f618ec571e10e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Jul 2006 17:08:42 -0400 Subject: [PATCH 3/5] BUG#20893: Valgrind error mysql-test/r/partition_mgm.result: Added new test case mysql-test/t/partition_mgm.test: Added new test case sql/ha_partition.cc: Fixed memory overwrite, added new variable for memory check Problem was when reorganising partitions, the file handles got in the wrong place. sql/ha_partition.h: Added new variable for debugging mostly --- mysql-test/r/partition_mgm.result | 12 ++++++++++++ mysql-test/t/partition_mgm.test | 16 +++++++++++++++- sql/ha_partition.cc | 15 +++++++++++---- sql/ha_partition.h | 1 + 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index 0f2c8c57872..f64ffaff495 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -24,3 +24,15 @@ hello/master-data/test/t1#P#p0.MYD hello/master-data/test/t1#P#p0.MYI hello/master-data/test/t1.frm hello/master-data/test/t1.par +drop table t1; +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), +partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), +partition p12 values in (3,4)); +drop table t1; diff --git a/mysql-test/t/partition_mgm.test b/mysql-test/t/partition_mgm.test index cfb76192de4..39512de154f 100644 --- a/mysql-test/t/partition_mgm.test +++ b/mysql-test/t/partition_mgm.test @@ -12,7 +12,21 @@ ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; --replace_result $MYSQLTEST_VARDIR "hello" --exec ls $MYSQLTEST_VARDIR/master-data/test/t1* +drop table t1; +# +# Bug 20767: REORGANIZE partition crashes +# +create table t1 (a int) +partition by list (a) +subpartition by hash (a) +(partition p11 values in (1,2), + partition p12 values in (3,4)); +alter table t1 REORGANIZE partition p11, p12 INTO +(partition p1 values in (1,2,3,4)); +alter table t1 REORGANIZE partition p1 INTO +(partition p11 values in (1,2), + partition p12 values in (3,4)); - +drop table t1; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..1ee1c1b51cf 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -204,6 +204,7 @@ void ha_partition::init_handler_variables() m_name_buffer_ptr= NULL; m_engine_array= NULL; m_file= NULL; + m_file_tot_parts= 0; m_reorged_file= NULL; m_new_file= NULL; m_reorged_parts= 0; @@ -1231,7 +1232,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, uint no_parts= m_part_info->partitions.elements; uint no_subparts= m_part_info->no_subparts; uint i= 0; - uint no_remain_partitions, part_count; + uint no_remain_partitions, part_count, orig_count; handler **new_file_array; int error= 1; bool first; @@ -1266,10 +1267,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, } while (++i < no_parts); } if (m_reorged_parts && - !(m_reorged_file= (handler**)sql_calloc(sizeof(partition_element*)* + !(m_reorged_file= (handler**)sql_calloc(sizeof(handler*)* (m_reorged_parts + 1)))) { - mem_alloc_error(sizeof(partition_element*)*(m_reorged_parts+1)); + mem_alloc_error(sizeof(handler*)*(m_reorged_parts+1)); DBUG_RETURN(ER_OUTOFMEMORY); } @@ -1340,6 +1341,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, ones used to be. */ first= FALSE; + DBUG_ASSERT(i + m_reorged_parts <= m_file_tot_parts); memcpy((void*)m_reorged_file, &m_file[i*no_subparts], sizeof(handler*)*m_reorged_parts*no_subparts); } @@ -1353,15 +1355,18 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, */ i= 0; part_count= 0; + orig_count= 0; part_it.rewind(); do { partition_element *part_elem= part_it++; if (part_elem->part_state == PART_NORMAL) { - memcpy((void*)&new_file_array[part_count], (void*)&m_file[i], + DBUG_ASSERT(orig_count + no_subparts <= m_file_tot_parts); + memcpy((void*)&new_file_array[part_count], (void*)&m_file[orig_count], sizeof(handler*)*no_subparts); part_count+= no_subparts; + orig_count+= no_subparts; } else if (part_elem->part_state == PART_CHANGED || part_elem->part_state == PART_TO_BE_ADDED) @@ -1959,6 +1964,7 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) if (!(m_file= (handler **) alloc_root(mem_root, alloc_len))) DBUG_RETURN(TRUE); + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); for (i= 0; i < m_tot_parts; i++) { @@ -2008,6 +2014,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root) mem_alloc_error(alloc_len); goto error_end; } + m_file_tot_parts= m_tot_parts; bzero((char*) m_file, alloc_len); DBUG_ASSERT(m_part_info->no_parts > 0); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..73ec7f60df5 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -55,6 +55,7 @@ private: char *m_name_buffer_ptr; // Pointer to first partition name handlerton **m_engine_array; // Array of types of the handlers handler **m_file; // Array of references to handler inst. + uint m_file_tot_parts; // Debug handler **m_new_file; // Array of references to new handlers handler **m_reorged_file; // Reorganised partitions handler **m_added_file; // Added parts kept for errors From cb3a82a0fcc592bc6bb1ee6514f6a43ef37b4fa9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Jul 2006 20:38:17 -0400 Subject: [PATCH 4/5] BUG#20852: Using update with full table scan causes mysqld to enter an eternal loop mysql-test/r/partition_innodb.result: New test case mysql-test/t/partition_innodb.test: New test case sql/ha_partition.cc: Two more handler interface variables not taken care of --- mysql-test/r/partition_innodb.result | 11 +++++++++++ mysql-test/t/partition_innodb.test | 13 +++++++++++++ sql/ha_partition.cc | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 5e5931fdbf8..73745aad58b 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -107,3 +107,14 @@ select * from t1 where id = 'aaa'; id aaa drop table t1; +create table t1 (a int, b int, primary key (b,a)) +engine = innodb +partition by hash (a); +insert into t1 values (0, 0); +insert into t1 values (1, 0); +update t1 set b = b + 1 where a = 1; +select * from t1; +a b +0 0 +1 1 +drop table t1; diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 51f5b0fec01..e40d9fffbf8 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -78,3 +78,16 @@ select * from t1 where id = 'a'; select * from t1 where id = 'aa'; select * from t1 where id = 'aaa'; drop table t1; + +# +# Bug #20852 Partitions: Crash if hash innodb, composite primary key +# +create table t1 (a int, b int, primary key (b,a)) +engine = innodb +partition by hash (a); +insert into t1 values (0, 0); +insert into t1 values (1, 0); +update t1 set b = b + 1 where a = 1; +select * from t1; +drop table t1; + diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..a02971f9f66 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2229,7 +2229,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_table_flags&= ~(HA_CAN_GEOMETRY | HA_CAN_FULLTEXT | HA_DUPLICATE_POS | HA_CAN_SQL_HANDLER | HA_CAN_INSERT_DELAYED); m_table_flags|= HA_FILE_BASED | HA_REC_NOT_IN_SEQ; - + key_used_on_scan= m_file[0]->key_used_on_scan; + implicit_emptied= m_file[0]->implicit_emptied; /* Add 2 bytes for partition id in position ref length. ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS From dd7290571674e26cdd5f1be5304d15291517d6fa Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 15 Jul 2006 03:38:34 -0400 Subject: [PATCH 5/5] BUG#20389: Crash when using index scan in reverse order mysql-test/r/partition_order.result: Changed a test case to handle ordered index scan reverse order as well mysql-test/t/partition_order.test: Changed a test case to handle ordered index scan reverse order as well sql/ha_myisam.cc: More debug info sql/ha_partition.cc: Introduced partition_index_read_last to ensure we use index_read_last in those cases towards underlying handler. Ensured that index_read with HA_READ_PREFIX_LAST, HA_READ_PREFIX_LAST_OR_PREV and HA_READ_BEFORE_KEY uses ordered index scan in reverse order. sql/ha_partition.h: Introduced partition_index_read_last to ensure we use index_read_last in those cases towards underlying handler. Ensured that index_read with HA_READ_PREFIX_LAST, HA_READ_PREFIX_LAST_OR_PREV and HA_READ_BEFORE_KEY uses ordered index scan in reverse order. --- mysql-test/r/partition_order.result | 56 +++++++++++++++++++++++++++-- mysql-test/t/partition_order.test | 20 +++++++++-- sql/ha_myisam.cc | 3 +- sql/ha_partition.cc | 30 +++++++++++----- sql/ha_partition.h | 5 +-- 5 files changed, 99 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/partition_order.result b/mysql-test/r/partition_order.result index 7a1ab1d6dc8..78ff7cd3121 100644 --- a/mysql-test/r/partition_order.result +++ b/mysql-test/r/partition_order.result @@ -718,7 +718,11 @@ partitions 2 partition x2 values less than (100)); INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); @@ -727,7 +731,55 @@ a b 5 NULL 40 NULL 1 1 +7 1 35 2 +3 3 +2 4 30 4 -2 5 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b; +a b +1 1 +7 1 +35 2 +3 3 +2 4 +30 4 +4 5 +6 6 +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +a b +6 6 +4 5 +2 4 +30 4 +3 3 +35 2 +7 1 +1 1 +drop table t1; +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), +partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL +select * from t1 where a = 1 order by b desc; +a b c +1 9 9 +1 7 7 +1 5 5 +1 3 3 +1 1 1 +1 NULL NULL drop table t1; diff --git a/mysql-test/t/partition_order.test b/mysql-test/t/partition_order.test index 1e1b3339d64..ad956361d00 100644 --- a/mysql-test/t/partition_order.test +++ b/mysql-test/t/partition_order.test @@ -818,11 +818,27 @@ partitions 2 # Insert a couple of tuples INSERT into t1 values (1, 1); INSERT into t1 values (5, NULL); -INSERT into t1 values (2, 5); +INSERT into t1 values (2, 4); +INSERT into t1 values (3, 3); +INSERT into t1 values (4, 5); +INSERT into t1 values (7, 1); +INSERT into t1 values (6, 6); INSERT into t1 values (30, 4); INSERT into t1 values (35, 2); INSERT into t1 values (40, NULL); select * from t1 force index (b) where b < 10 OR b IS NULL order by b; - +select * from t1 force index (b) where b < 10 ORDER BY b; +select * from t1 force index (b) where b < 10 ORDER BY b DESC; +drop table t1; + +create table t1 (a int not null, b int, c varchar(20), key (a,b,c)) +partition by range (b) +(partition p0 values less than (5), + partition p1 values less than (10)); +INSERT into t1 values (1,1,'1'),(2,2,'2'),(1,3,'3'),(2,4,'4'),(1,5,'5'); +INSERT into t1 values (2,6,'6'),(1,7,'7'),(2,8,'8'),(1,9,'9'); +INSERT into t1 values (1, NULL, NULL), (2, NULL, '10'); +select * from t1 where a = 1 order by a desc, b desc; +select * from t1 where a = 1 order by b desc; drop table t1; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 2d097c34f97..2acc1f4ed7d 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1202,12 +1202,13 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key, int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len) { + DBUG_ENTER("ha_myisam::index_read_last"); DBUG_ASSERT(inited==INDEX); statistic_increment(table->in_use->status_var.ha_read_key_count, &LOCK_status); int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST); table->status=error ? STATUS_NOT_FOUND: 0; - return error; + DBUG_RETURN(error); } int ha_myisam::index_next(byte * buf) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index c0257e08537..3d7f8fc5fb2 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3265,6 +3265,7 @@ int ha_partition::index_read(byte * buf, const byte * key, DBUG_ENTER("ha_partition::index_read"); end_range= 0; + m_index_scan_type= partition_index_read; DBUG_RETURN(common_index_read(buf, key, key_len, find_flag)); } @@ -3282,18 +3283,24 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, enum ha_rkey_function find_flag) { int error; + bool reverse_order= FALSE; DBUG_ENTER("ha_partition::common_index_read"); memcpy((void*)m_start_key.key, key, key_len); m_start_key.length= key_len; m_start_key.flag= find_flag; - m_index_scan_type= partition_index_read; if ((error= partition_scan_set_up(buf, TRUE))) { DBUG_RETURN(error); } - + if (find_flag == HA_READ_PREFIX_LAST || + find_flag == HA_READ_PREFIX_LAST_OR_PREV || + find_flag == HA_READ_BEFORE_KEY) + { + reverse_order= TRUE; + m_ordered_scan_ongoing= TRUE; + } if (!m_ordered_scan_ongoing || (find_flag == HA_READ_KEY_EXACT && (key_len >= m_curr_key_info->key_length || @@ -3319,7 +3326,7 @@ int ha_partition::common_index_read(byte *buf, const byte *key, uint key_len, In all other cases we will use the ordered index scan. This will use the partition set created by the get_partition_set method. */ - error= handle_ordered_index_scan(buf); + error= handle_ordered_index_scan(buf, reverse_order); } DBUG_RETURN(error); } @@ -3403,7 +3410,7 @@ int ha_partition::common_first_last(byte *buf) if (!m_ordered_scan_ongoing && m_index_scan_type != partition_index_last) return handle_unordered_scan_next_partition(buf); - return handle_ordered_index_scan(buf); + return handle_ordered_index_scan(buf, FALSE); } @@ -3457,7 +3464,9 @@ int ha_partition::index_read_last(byte *buf, const byte *key, uint keylen) DBUG_ENTER("ha_partition::index_read_last"); m_ordered= TRUE; // Safety measure - DBUG_RETURN(index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); + end_range= 0; + m_index_scan_type= partition_index_read_last; + DBUG_RETURN(common_index_read(buf, key, keylen, HA_READ_PREFIX_LAST)); } @@ -3597,6 +3606,7 @@ int ha_partition::read_range_first(const key_range *start_key, } else { + m_index_scan_type= partition_index_read; error= common_index_read(m_rec0, start_key->key, start_key->length, start_key->flag); @@ -3855,12 +3865,11 @@ int ha_partition::handle_unordered_scan_next_partition(byte * buf) entries. */ -int ha_partition::handle_ordered_index_scan(byte *buf) +int ha_partition::handle_ordered_index_scan(byte *buf, bool reverse_order) { uint i; uint j= 0; bool found= FALSE; - bool reverse_order= FALSE; DBUG_ENTER("ha_partition::handle_ordered_index_scan"); m_top_entry= NO_CURRENT_PART_ID; @@ -3881,7 +3890,6 @@ int ha_partition::handle_ordered_index_scan(byte *buf) m_start_key.key, m_start_key.length, m_start_key.flag); - reverse_order= FALSE; break; case partition_index_first: error= file->index_first(rec_buf_ptr); @@ -3891,6 +3899,12 @@ int ha_partition::handle_ordered_index_scan(byte *buf) error= file->index_last(rec_buf_ptr); reverse_order= TRUE; break; + case partition_index_read_last: + error= file->index_read_last(rec_buf_ptr, + m_start_key.key, + m_start_key.length); + reverse_order= TRUE; + break; default: DBUG_ASSERT(FALSE); DBUG_RETURN(HA_ERR_END_OF_FILE); diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 4c627cd50f8..b838bc599f0 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -46,7 +46,8 @@ private: partition_index_read= 0, partition_index_first= 1, partition_index_last= 2, - partition_no_index_scan= 3 + partition_index_read_last= 3, + partition_no_index_scan= 4 }; /* Data for the partition handler */ int m_mode; // Open mode @@ -429,7 +430,7 @@ private: return (queue_buf(part_id) + PARTITION_BYTES_IN_POS); } - int handle_ordered_index_scan(byte * buf); + int handle_ordered_index_scan(byte * buf, bool reverse_order); int handle_ordered_next(byte * buf, bool next_same); int handle_ordered_prev(byte * buf); void return_top_record(byte * buf);