From: Date: March 27 2007 1:15pm Subject: bk commit into 5.1 tree (holyfoot:1.2501) BUG#27084 List-Archive: http://lists.mysql.com/commits/22997 X-Bug: 27084 Message-Id: <20070327111543.7D57C2C380B7@hfmain.localdomain> Below is the list of changes that have just been committed into a local 5.1 repository of hf. When hf does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-03-27 16:15:38+05:00, holyfoot@stripped +7 -0 Bug #27084 partitioning by list seems failing when using case creation of the partitioned table could fail as we created Item-s for it's list function in thd->mem_root, and then do Item->fix_fields in the context of other table->mem_root (so that memory alloced there was alloced in this table->mem_root). As we freed the table->mem_root before we do thd->free_items, our Item-s had pointers to the freed memory, that caused the crash mysql-test/r/partition.result@stripped, 2007-03-27 16:15:34+05:00, holyfoot@stripped +10 -0 result mysql-test/t/partition.test@stripped, 2007-03-27 16:15:34+05:00, holyfoot@stripped +15 -0 testcase sql/item_cmpfunc.cc@stripped, 2007-03-27 16:15:35+05:00, holyfoot@stripped +15 -0 here is better place for the implementation sql/item_cmpfunc.h@stripped, 2007-03-27 16:15:35+05:00, holyfoot@stripped +1 -12 implementation moved to .cc file sql/sql_partition.cc@stripped, 2007-03-27 16:15:35+05:00, holyfoot@stripped +6 -1 work_part_info_used parameter added to mysql_unpack_partition sql/sql_partition.h@stripped, 2007-03-27 16:15:35+05:00, holyfoot@stripped +2 -1 work_part_info_used parameter added to mysql_unpack_partition sql/table.cc@stripped, 2007-03-27 16:15:35+05:00, holyfoot@stripped +11 -2 we do 'fix_partition_func' using the proper arena now. It's necessary as Item_*::fix_fields can alloc memory using thd->mem_root and this has to be same mem_root that we used to alloc these Item-s # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: holyfoot # Host: hfmain.(none) # Root: /home/hf/work/27084/my51-27084 --- 1.257/sql/item_cmpfunc.cc 2007-03-27 16:15:43 +05:00 +++ 1.258/sql/item_cmpfunc.cc 2007-03-27 16:15:43 +05:00 @@ -2099,6 +2099,21 @@ void Item_func_case::print(String *str) str->append(STRING_WITH_LEN("end)")); } + +void Item_func_case::cleanup() +{ + uint i; + DBUG_ENTER("Item_func_case::cleanup"); + Item_func::cleanup(); + for (i= 0; i <= (uint)DECIMAL_RESULT; i++) + { + delete cmp_items[i]; + cmp_items[i]= 0; + } + DBUG_VOID_RETURN; +} + + /* Coalesce - return first not NULL argument. */ --- 1.157/sql/item_cmpfunc.h 2007-03-27 16:15:43 +05:00 +++ 1.158/sql/item_cmpfunc.h 2007-03-27 16:15:43 +05:00 @@ -1106,18 +1106,7 @@ public: Item *find_item(String *str); CHARSET_INFO *compare_collation() { return cmp_collation.collation; } bool check_partition_func_processor(byte *bool_arg) { return FALSE;} - void cleanup() - { - uint i; - DBUG_ENTER("Item_func_case::cleanup"); - Item_func::cleanup(); - for (i= 0; i <= (uint)DECIMAL_RESULT; i++) - { - delete cmp_items[i]; - cmp_items[i]= 0; - } - DBUG_VOID_RETURN; - } + void cleanup(); }; /* --- 1.281/sql/table.cc 2007-03-27 16:15:43 +05:00 +++ 1.282/sql/table.cc 2007-03-27 16:15:43 +05:00 @@ -1525,21 +1525,30 @@ int open_table_from_share(THD *thd, TABL thd->set_n_backup_active_arena(&part_func_arena, &backup_arena); thd->stmt_arena= &part_func_arena; bool tmp; + bool work_part_info_used; tmp= mysql_unpack_partition(thd, share->partition_info, share->partition_info_len, (uchar*)share->part_state, share->part_state_len, outparam, is_create_table, - share->default_part_db_type); + share->default_part_db_type, + &work_part_info_used); outparam->part_info->is_auto_partitioned= share->auto_partitioned; DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); - if (!tmp) + /* we should perform the fix_partition_func in either local or + caller's arena depending on work_part_info_used value + */ + if (!tmp && !work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); thd->stmt_arena= backup_stmt_arena_ptr; thd->restore_active_arena(&part_func_arena, &backup_arena); if (!tmp) + { + if (work_part_info_used) + tmp= fix_partition_func(thd, outparam, is_create_table); outparam->part_info->item_free_list= part_func_arena.free_list; + } if (tmp) { if (is_create_table) --- 1.58/mysql-test/r/partition.result 2007-03-27 16:15:43 +05:00 +++ 1.59/mysql-test/r/partition.result 2007-03-27 16:15:43 +05:00 @@ -1219,4 +1219,14 @@ SELECT t2.id FROM t2 WHERE t2.id IN (SEL id 22589 drop table t1, t2; +CREATE TABLE `t1` ( `a` varchar(1)) ENGINE=MyISAM +PARTITION BY LIST (CASE a WHEN 'a' THEN 1 +WHEN 'b' THEN 2 +WHEN 'c' THEN 3 +END) ( +PARTITION a VALUES IN (1), +PARTITION b VALUES IN (2), +PARTITION c VALUES IN (3) +); +DROP TABLE t1; End of 5.1 tests --- 1.52/mysql-test/t/partition.test 2007-03-27 16:15:43 +05:00 +++ 1.53/mysql-test/t/partition.test 2007-03-27 16:15:43 +05:00 @@ -1463,4 +1463,19 @@ SELECT t2.id FROM t2 WHERE t2.id IN (SEL drop table t1, t2; +# +# Bug #27084 partitioning by list seems failing when using case +# +CREATE TABLE `t1` ( `a` varchar(1)) ENGINE=MyISAM + PARTITION BY LIST (CASE a WHEN 'a' THEN 1 + WHEN 'b' THEN 2 + WHEN 'c' THEN 3 + END) ( + PARTITION a VALUES IN (1), + PARTITION b VALUES IN (2), + PARTITION c VALUES IN (3) +); + +DROP TABLE t1; + --echo End of 5.1 tests --- 1.100/sql/sql_partition.cc 2007-03-27 16:15:43 +05:00 +++ 1.101/sql/sql_partition.cc 2007-03-27 16:15:43 +05:00 @@ -3684,6 +3684,8 @@ void get_partition_set(const TABLE *tabl table Table object of partitioned table create_table_ind Is it called from CREATE TABLE default_db_type What is the default engine of the table + work_part_info_used Flag is raised if we don't create new + part_info, but used thd->work_part_info RETURN VALUE TRUE Error @@ -3704,7 +3706,8 @@ bool mysql_unpack_partition(THD *thd, co uint part_info_len, uchar *part_state, uint part_state_len, TABLE* table, bool is_create_table_ind, - handlerton *default_db_type) + handlerton *default_db_type, + bool *work_part_info_used) { bool result= TRUE; partition_info *part_info; @@ -3716,6 +3719,7 @@ bool mysql_unpack_partition(THD *thd, co thd->lex= &lex; thd->variables.character_set_client= system_charset_info; lex_start(thd, part_buf, part_info_len); + *work_part_info_used= false; /* We need to use the current SELECT_LEX since I need to keep the Name_resolution_context object which is referenced from the @@ -3805,6 +3809,7 @@ bool mysql_unpack_partition(THD *thd, co thd->free_items(); part_info= thd->work_part_info; table->s->version= 0UL; + *work_part_info_used= true; } } table->part_info= part_info; --- 1.13/sql/sql_partition.h 2007-03-27 16:15:43 +05:00 +++ 1.14/sql/sql_partition.h 2007-03-27 16:15:43 +05:00 @@ -81,7 +81,8 @@ bool mysql_unpack_partition(THD *thd, co uint part_info_len, uchar *part_state, uint part_state_len, TABLE *table, bool is_create_table_ind, - handlerton *default_db_type); + handlerton *default_db_type, + bool *work_part_info_used); void make_used_partitions_str(partition_info *part_info, String *parts_str); uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool left_endpoint,