From: Date: August 5 2008 9:50am Subject: bzr commit into mysql-5.1 branch (holyfoot:2683) Bug#38083 List-Archive: http://lists.mysql.com/commits/50910 X-Bug: 38083 Message-Id: <20080805075040.3412D2C380A5@hfmain.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/hf/work/mysql_common/38083/ 2683 Alexey Botchkov 2008-08-05 Bug#38083 Error-causing row inserted into partitioned table despite error problems are located in the sql_partition.cc where functions calculation partition_id don't expect error returned from item->val_int(). Fixed by adding checks to these functions. Note - it tries to fix more problems than just the reported bug per-file comments: mysql-test/r/partition_error.result Bug#38083 Error-causing row inserted into partitioned table despite error test result mysql-test/t/partition_error.test Bug#38083 Error-causing row inserted into partitioned table despite error test case sql/sql_partition.cc Bug#38083 Error-causing row inserted into partitioned table despite error various functions calculationg partition_id didn't expect an error returned from item->val_int(). Error checks added. modified: mysql-test/r/partition_error.result mysql-test/t/partition_error.test sql/sql_partition.cc === modified file 'mysql-test/r/partition_error.result' --- a/mysql-test/r/partition_error.result 2008-02-25 20:18:50 +0000 +++ b/mysql-test/r/partition_error.result 2008-08-05 07:40:32 +0000 @@ -642,3 +642,22 @@ ERROR HY000: This partition function is create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); ERROR HY000: This partition function is not allowed +set @orig_sql_mode = @@sql_mode; +SET SQL_MODE='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO'; +CREATE TABLE t1 (c1 INT) +PARTITION BY LIST(1 DIV c1) ( +PARTITION p0 VALUES IN (NULL), +PARTITION p1 VALUES IN (1) +); +INSERT INTO t1 VALUES (0); +ERROR 22012: Division by 0 +SELECT * FROM t1; +c1 +TRUNCATE t1; +INSERT INTO t1 VALUES (NULL), (0), (1), (2); +ERROR 22012: Division by 0 +SELECT * FROM t1; +c1 +NULL +DROP TABLE t1; +set sql_mode= @orig_sql_mode; === modified file 'mysql-test/t/partition_error.test' --- a/mysql-test/t/partition_error.test 2008-02-25 20:18:50 +0000 +++ b/mysql-test/t/partition_error.test 2008-08-05 07:40:32 +0000 @@ -826,4 +826,23 @@ partition by range (a + (select count(*) create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); +# +# Bug #38083 Error-causing row inserted into partitioned table despite error +# +set @orig_sql_mode = @@sql_mode; +SET SQL_MODE='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO'; +CREATE TABLE t1 (c1 INT) + PARTITION BY LIST(1 DIV c1) ( + PARTITION p0 VALUES IN (NULL), + PARTITION p1 VALUES IN (1) + ); +-- error ER_DIVISION_BY_ZERO +INSERT INTO t1 VALUES (0); +SELECT * FROM t1; +TRUNCATE t1; +-- error ER_DIVISION_BY_ZERO +INSERT INTO t1 VALUES (NULL), (0), (1), (2); +SELECT * FROM t1; +DROP TABLE t1; +set sql_mode= @orig_sql_mode; === modified file 'sql/sql_partition.cc' --- a/sql/sql_partition.cc 2008-07-15 01:43:12 +0000 +++ b/sql/sql_partition.cc 2008-08-05 07:40:32 +0000 @@ -2319,16 +2319,19 @@ static uint32 get_part_id_for_sub(uint32 get_part_id_hash() no_parts Number of hash partitions part_expr Item tree of hash function - out:func_value Value of hash function + out:part_id The returned partition id + out:func_value Value of hash function RETURN VALUE - Calculated partition id + FALSE Success + TRUE Failure */ inline -static uint32 get_part_id_hash(uint no_parts, - Item *part_expr, - longlong *func_value) +static int get_part_id_hash(uint no_parts, + Item *part_expr, + uint32 *part_id, + longlong *func_value) { longlong int_hash_id; DBUG_ENTER("get_part_id_hash"); @@ -2336,7 +2339,8 @@ static uint32 get_part_id_hash(uint no_p *func_value= part_val_int(part_expr); int_hash_id= *func_value % no_parts; - DBUG_RETURN(int_hash_id < 0 ? (uint32) -int_hash_id : (uint32) int_hash_id); + *part_id= int_hash_id < 0 ? (uint32) -int_hash_id : (uint32) int_hash_id; + DBUG_RETURN(current_thd->is_error()); } @@ -2349,24 +2353,30 @@ static uint32 get_part_id_hash(uint no_p desired information is given no_parts Number of hash partitions part_expr Item tree of hash function + out:part_id The returned partition id out:func_value Value of hash function RETURN VALUE - Calculated partition id + FALSE Success + TRUE Failure */ inline -static uint32 get_part_id_linear_hash(partition_info *part_info, - uint no_parts, - Item *part_expr, - longlong *func_value) +static int get_part_id_linear_hash(partition_info *part_info, + uint no_parts, + Item *part_expr, + uint32 *part_id, + longlong *func_value) { DBUG_ENTER("get_part_id_linear_hash"); *func_value= part_val_int(part_expr); - DBUG_RETURN(get_part_id_from_linear_hash(*func_value, - part_info->linear_hash_mask, - no_parts)); + if (current_thd->is_error()) + DBUG_RETURN(TRUE); + *part_id= get_part_id_from_linear_hash(*func_value, + part_info->linear_hash_mask, + no_parts); + DBUG_RETURN(FALSE); } @@ -2666,6 +2676,8 @@ int get_partition_id_list(partition_info bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_list"); + if (current_thd->is_error()) + goto notfound; if (part_info->part_expr->null_value) { if (part_info->has_null_value) @@ -2813,6 +2825,9 @@ int get_partition_id_range(partition_inf bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_range"); + if (current_thd->is_error()) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + if (part_info->part_expr->null_value) { *part_id= 0; @@ -2970,9 +2985,8 @@ int get_partition_id_hash_nosub(partitio uint32 *part_id, longlong *func_value) { - *part_id= get_part_id_hash(part_info->no_parts, part_info->part_expr, - func_value); - return 0; + return get_part_id_hash(part_info->no_parts, part_info->part_expr, + part_id, func_value); } @@ -2980,9 +2994,8 @@ int get_partition_id_linear_hash_nosub(p uint32 *part_id, longlong *func_value) { - *part_id= get_part_id_linear_hash(part_info, part_info->no_parts, - part_info->part_expr, func_value); - return 0; + return get_part_id_linear_hash(part_info, part_info->no_parts, + part_info->part_expr, part_id, func_value); } @@ -3023,8 +3036,10 @@ int get_partition_id_range_sub_hash(part DBUG_RETURN(error); } no_subparts= part_info->no_subparts; - sub_part_id= get_part_id_hash(no_subparts, part_info->subpart_expr, - &local_func_value); + if (get_part_id_hash(no_subparts, part_info->subpart_expr, + &sub_part_id, &local_func_value)) + DBUG_RETURN(1); + *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); DBUG_RETURN(0); } @@ -3046,9 +3061,11 @@ int get_partition_id_range_sub_linear_ha DBUG_RETURN(error); } no_subparts= part_info->no_subparts; - sub_part_id= get_part_id_linear_hash(part_info, no_subparts, - part_info->subpart_expr, - &local_func_value); + if (get_part_id_linear_hash(part_info, no_subparts, + part_info->subpart_expr, + &sub_part_id, + &local_func_value)) + DBUG_RETURN(1); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); DBUG_RETURN(0); } @@ -3117,8 +3134,9 @@ int get_partition_id_list_sub_hash(parti DBUG_RETURN(error); } no_subparts= part_info->no_subparts; - sub_part_id= get_part_id_hash(no_subparts, part_info->subpart_expr, - &local_func_value); + if (get_part_id_hash(no_subparts, part_info->subpart_expr, + &sub_part_id, &local_func_value)) + DBUG_RETURN(1); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); DBUG_RETURN(0); } @@ -3140,9 +3158,11 @@ int get_partition_id_list_sub_linear_has DBUG_RETURN(error); } no_subparts= part_info->no_subparts; - sub_part_id= get_part_id_linear_hash(part_info, no_subparts, - part_info->subpart_expr, - &local_func_value); + if (get_part_id_linear_hash(part_info, no_subparts, + part_info->subpart_expr, + &sub_part_id, + &local_func_value)) + DBUG_RETURN(1); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); DBUG_RETURN(0); } @@ -3222,16 +3242,20 @@ int get_partition_id_list_sub_linear_key uint32 get_partition_id_hash_sub(partition_info *part_info) { longlong func_value; - return get_part_id_hash(part_info->no_subparts, part_info->subpart_expr, - &func_value); + uint32 part_id; + (void) get_part_id_hash(part_info->no_subparts, part_info->subpart_expr, + &part_id, &func_value); + return part_id; } uint32 get_partition_id_linear_hash_sub(partition_info *part_info) { longlong func_value; - return get_part_id_linear_hash(part_info, part_info->no_subparts, - part_info->subpart_expr, &func_value); + uint32 part_id; + (void) get_part_id_linear_hash(part_info, part_info->no_subparts, + part_info->subpart_expr, &part_id, &func_value); + return part_id; }