From: Date: September 22 2008 10:26am Subject: bzr commit into mysql-5.1 branch (holyfoot:2743) Bug#38083 List-Archive: http://lists.mysql.com/commits/54447 X-Bug: 38083 Message-Id: <20080922082634.0D69C2C380C0@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/ 2743 Alexey Botchkov 2008-09-22 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. get_part_id_* functions return HA_ERR_NO_PARTITION_FOUND in the *part_id out parameter in the case of the error. per-file comments: mysql-test/r/partition.result Bug#38083 Error-causing row inserted into partitioned table despite error test result mysql-test/t/partition.test Bug#38083 Error-causing row inserted into partitioned table despite error test case sql/ha_ndbcluster.cc Bug#38083 Error-causing row inserted into partitioned table despite error get_part_id() call fixed sql/ha_partition.cc Bug#38083 Error-causing row inserted into partitioned table despite error get_part_id() call fixed sql/opt_range.cc Bug#38083 Error-causing row inserted into partitioned table despite error get_part_id() call fixed sql/partition_info.h Bug#38083 Error-causing row inserted into partitioned table despite error get_subpart_id_func interface changed. sql/sql_partition.cc Bug#38083 Error-causing row inserted into partitioned table despite error various functions calculationg partition_id and subpart_id didn't expect an error returned from item->val_int(). Error checks added. modified: mysql-test/r/partition.result mysql-test/t/partition.test sql/ha_ndbcluster.cc sql/ha_partition.cc sql/opt_range.cc sql/partition_info.h sql/sql_partition.cc === modified file 'mysql-test/r/partition.result' --- a/mysql-test/r/partition.result 2008-08-15 18:26:25 +0000 +++ b/mysql-test/r/partition.result 2008-09-22 08:20:18 +0000 @@ -1637,4 +1637,23 @@ select count(*) from t1, t2 where t1.cre count(*) 1 drop table t1, t2; +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; End of 5.1 tests === modified file 'mysql-test/t/partition.test' --- a/mysql-test/t/partition.test 2008-08-15 18:26:25 +0000 +++ b/mysql-test/t/partition.test 2008-09-22 08:20:18 +0000 @@ -1791,4 +1791,26 @@ select count(*) from t1, t2 where t1.cre drop table t1, t2; +# +# 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; + + --echo End of 5.1 tests === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2008-09-15 09:19:56 +0000 +++ b/sql/ha_ndbcluster.cc 2008-09-22 08:20:18 +0000 @@ -2011,7 +2011,7 @@ int ha_ndbcluster::peek_indexed_rows(con if (error) { m_part_info->err_value= func_value; - DBUG_RETURN(error); + DBUG_RETURN(part_id); } op->setPartitionId(part_id); } @@ -2794,7 +2794,7 @@ int ha_ndbcluster::write_row(uchar *reco if (error) { m_part_info->err_value= func_value; - DBUG_RETURN(error); + DBUG_RETURN(part_id); } op->setPartitionId(part_id); } === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2008-08-20 15:29:14 +0000 +++ b/sql/ha_partition.cc 2008-09-22 08:20:18 +0000 @@ -2896,6 +2896,7 @@ int ha_partition::write_row(uchar * buf) dbug_tmp_restore_column_map(table->read_set, old_map); if (unlikely(error)) { + error= part_id; m_part_info->err_value= func_value; goto exit; } === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2008-08-25 17:18:22 +0000 +++ b/sql/opt_range.cc 2008-09-22 08:20:18 +0000 @@ -3145,10 +3145,12 @@ int find_used_partitions(PART_PRUNE_PARA ppar->subpart_fields);); /* Find the subpartition (it's HASH/KEY so we always have one) */ partition_info *part_info= ppar->part_info; - uint32 subpart_id= part_info->get_subpartition_id(part_info); + uint32 part_id, subpart_id; + if (part_info->get_subpartition_id(part_info, &subpart_id)) + return 0; + /* Mark this partition as used in each subpartition. */ - uint32 part_id; while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) != NOT_A_PARTITION_ID) { === modified file 'sql/partition_info.h' --- a/sql/partition_info.h 2008-03-16 08:52:37 +0000 +++ b/sql/partition_info.h 2008-09-22 08:20:18 +0000 @@ -25,7 +25,8 @@ class partition_info; typedef int (*get_part_id_func)(partition_info *part_info, uint32 *part_id, longlong *func_value); -typedef uint32 (*get_subpart_id_func)(partition_info *part_info); +typedef int (*get_subpart_id_func)(partition_info *part_info, + uint32 *part_id); struct st_ddl_log_memory_entry; === modified file 'sql/sql_partition.cc' --- a/sql/sql_partition.cc 2008-08-11 18:02:03 +0000 +++ b/sql/sql_partition.cc 2008-09-22 08:20:18 +0000 @@ -73,10 +73,8 @@ static int get_part_id_charset_func_subp static int get_part_part_id_charset_func(partition_info *part_info, uint32 *part_id, longlong *func_value); -static uint32 get_subpart_id_charset_func(partition_info *part_info); -int get_partition_id_list(partition_info *part_info, - uint32 *part_id, - longlong *func_value); +static int get_subpart_id_charset_func(partition_info *part_info, + uint32 *part_id); int get_partition_id_list(partition_info *part_info, uint32 *part_id, longlong *func_value); @@ -119,10 +117,14 @@ int get_partition_id_list_sub_linear_has int get_partition_id_list_sub_linear_key(partition_info *part_info, uint32 *part_id, longlong *func_value); -uint32 get_partition_id_hash_sub(partition_info *part_info); -uint32 get_partition_id_key_sub(partition_info *part_info); -uint32 get_partition_id_linear_hash_sub(partition_info *part_info); -uint32 get_partition_id_linear_key_sub(partition_info *part_info); +int get_partition_id_hash_sub(partition_info *part_info, + uint32 *part_id); +int get_partition_id_key_sub(partition_info *part_info, + uint32 *part_id); +int get_partition_id_linear_hash_sub(partition_info *part_info, + uint32 *part_id); +int get_partition_id_linear_key_sub(partition_info *part_info, + uint32 *part_id); static uint32 get_next_partition_via_walking(PARTITION_ITERATOR*); static void set_up_range_analysis_info(partition_info *part_info); static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR*); @@ -312,7 +314,7 @@ int get_parts_for_update(const uchar *ol if (unlikely(error)) // Should never happen { DBUG_ASSERT(0); - DBUG_RETURN(error); + DBUG_RETURN(*old_part_id); } #ifdef NOT_NEEDED if (new_data == rec0) @@ -322,7 +324,7 @@ int get_parts_for_update(const uchar *ol new_part_id, new_func_value))) { - DBUG_RETURN(error); + DBUG_RETURN(*new_part_id); } } #ifdef NOT_NEEDED @@ -339,7 +341,7 @@ int get_parts_for_update(const uchar *ol set_field_ptr(part_field_array, rec0, new_data); if (unlikely(error)) { - DBUG_RETURN(error); + DBUG_RETURN(*new_part_id); } } #endif @@ -380,7 +382,7 @@ int get_part_for_delete(const uchar *buf if (unlikely((error= part_info->get_partition_id(part_info, part_id, &func_value)))) { - DBUG_RETURN(error); + DBUG_RETURN(*part_id); } DBUG_PRINT("info", ("Delete from partition %d", *part_id)); } @@ -392,7 +394,7 @@ int get_part_for_delete(const uchar *buf set_field_ptr(part_field_array, rec0, buf); if (unlikely(error)) { - DBUG_RETURN(error); + DBUG_RETURN(*part_id); } DBUG_PRINT("info", ("Delete from partition %d (path2)", *part_id)); } @@ -2319,16 +2321,21 @@ 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 +2343,13 @@ 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; + if (current_thd->is_error()) + { + *part_id= HA_ERR_NO_PARTITION_FOUND; + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); } @@ -2349,24 +2362,34 @@ 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()) + { + *part_id= HA_ERR_NO_PARTITION_FOUND; + DBUG_RETURN(TRUE); + } + *part_id= get_part_id_from_linear_hash(*func_value, + part_info->linear_hash_mask, + no_parts); + DBUG_RETURN(FALSE); } @@ -2503,49 +2526,7 @@ static void restore_part_field_pointers( } return; } -/* - This function is used to calculate the partition id where all partition - fields have been prepared to point to a record where the partition field - values are bound. - - SYNOPSIS - get_partition_id() - part_info A reference to the partition_info struct where all the - desired information is given - out:part_id The partition id is returned through this pointer - out: func_value Value of partition function (longlong) - - RETURN VALUE - part_id Partition id of partition that would contain - row with given values of PF-fields - HA_ERR_NO_PARTITION_FOUND The fields of the partition function didn't - fit into any partition and thus the values of - the PF-fields are not allowed. - - DESCRIPTION - A routine used from write_row, update_row and delete_row from any - handler supporting partitioning. It is also a support routine for - get_partition_set used to find the set of partitions needed to scan - for a certain index scan or full table scan. - - It is actually 14 different variants of this function which are called - through a function pointer. - get_partition_id_list - get_partition_id_range - get_partition_id_hash_nosub - get_partition_id_key_nosub - get_partition_id_linear_hash_nosub - get_partition_id_linear_key_nosub - get_partition_id_range_sub_hash - get_partition_id_range_sub_key - get_partition_id_range_sub_linear_hash - get_partition_id_range_sub_linear_key - get_partition_id_list_sub_hash - get_partition_id_list_sub_key - get_partition_id_list_sub_linear_hash - get_partition_id_list_sub_linear_key -*/ /* This function is used to calculate the main partition to use in the case of @@ -2557,14 +2538,12 @@ static void restore_part_field_pointers( part_info A reference to the partition_info struct where all the desired information is given out:part_id The partition id is returned through this pointer - out: func_value The value calculated by partition function + out:func_value The value calculated by partition function RETURN VALUE - part_id Partition id of partition that would contain - row with given values of PF-fields - HA_ERR_NO_PARTITION_FOUND The fields of the partition function didn't - fit into any partition and thus the values of - the PF-fields are not allowed. + TRUE Error, the error code of HA_ERR_NO_PARTITION_FOUND + will be in part_id + FALSE correct part_id defined DESCRIPTION @@ -2640,13 +2619,14 @@ static int get_part_part_id_charset_func } -static uint32 get_subpart_id_charset_func(partition_info *part_info) +static int get_subpart_id_charset_func(partition_info *part_info, + uint32 *part_id) { int res; copy_to_part_field_buffers(part_info->subpart_charset_field_array, part_info->subpart_field_buffers, part_info->restore_subpart_field_ptrs); - res= part_info->get_subpartition_id_charset(part_info); + res= part_info->get_subpartition_id_charset(part_info, part_id); restore_part_field_pointers(part_info->subpart_charset_field_array, part_info->restore_subpart_field_ptrs); return res; @@ -2666,12 +2646,15 @@ 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) { *part_id= part_info->has_null_part_id; - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } goto notfound; } @@ -2693,12 +2676,12 @@ int get_partition_id_list(partition_info else { *part_id= (uint32)list_array[list_index].partition_id; - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } } notfound: - *part_id= 0; - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + *part_id= HA_ERR_NO_PARTITION_FOUND; + DBUG_RETURN(TRUE); } @@ -2813,10 +2796,16 @@ 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()) + { + *part_id= HA_ERR_NO_PARTITION_FOUND; + DBUG_RETURN(TRUE); + } + if (part_info->part_expr->null_value) { *part_id= 0; - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } *func_value= part_func_value; if (unsigned_flag) @@ -2837,10 +2826,13 @@ int get_partition_id_range(partition_inf if (loc_part_id == max_partition && part_func_value >= range_array[loc_part_id] && !part_info->defined_max_value) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + { + *part_id= HA_ERR_NO_PARTITION_FOUND; + DBUG_RETURN(TRUE); + } DBUG_PRINT("exit",("partition: %d", *part_id)); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -2970,9 +2962,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 +2971,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); } @@ -2992,7 +2982,7 @@ int get_partition_id_key_nosub(partition { *part_id= get_part_id_key(part_info->part_field_array, part_info->no_parts, func_value); - return 0; + return FALSE; } @@ -3003,7 +2993,7 @@ int get_partition_id_linear_key_nosub(pa *part_id= get_part_id_linear_key(part_info, part_info->part_field_array, part_info->no_parts, func_value); - return 0; + return FALSE; } @@ -3020,13 +3010,19 @@ int get_partition_id_range_sub_hash(part if (unlikely((error= get_partition_id_range(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; 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)) + { + *part_id= sub_part_id; + DBUG_RETURN(TRUE); + } + *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3043,14 +3039,21 @@ int get_partition_id_range_sub_linear_ha if (unlikely((error= get_partition_id_range(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; 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)) + { + *part_id= sub_part_id; + DBUG_RETURN(TRUE); + } + *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3067,13 +3070,14 @@ int get_partition_id_range_sub_key(parti if (unlikely((error= get_partition_id_range(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; DBUG_RETURN(error); } no_subparts= part_info->no_subparts; sub_part_id= get_part_id_key(part_info->subpart_field_array, no_subparts, &local_func_value); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3090,6 +3094,7 @@ int get_partition_id_range_sub_linear_ke if (unlikely((error= get_partition_id_range(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; DBUG_RETURN(error); } no_subparts= part_info->no_subparts; @@ -3097,7 +3102,7 @@ int get_partition_id_range_sub_linear_ke part_info->subpart_field_array, no_subparts, &local_func_value); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3114,13 +3119,19 @@ int get_partition_id_list_sub_hash(parti if (unlikely((error= get_partition_id_list(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; 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)) + { + *part_id= sub_part_id; + DBUG_RETURN(TRUE); + } + *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3137,14 +3148,21 @@ int get_partition_id_list_sub_linear_has if (unlikely((error= get_partition_id_list(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; 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)) + { + *part_id= sub_part_id; + DBUG_RETURN(TRUE); + } + *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3161,13 +3179,14 @@ int get_partition_id_list_sub_key(partit if (unlikely((error= get_partition_id_list(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; DBUG_RETURN(error); } no_subparts= part_info->no_subparts; sub_part_id= get_part_id_key(part_info->subpart_field_array, no_subparts, &local_func_value); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3184,6 +3203,7 @@ int get_partition_id_list_sub_linear_key if (unlikely((error= get_partition_id_list(part_info, &loc_part_id, func_value)))) { + *part_id= loc_part_id; DBUG_RETURN(error); } no_subparts= part_info->no_subparts; @@ -3191,7 +3211,7 @@ int get_partition_id_list_sub_linear_key part_info->subpart_field_array, no_subparts, &local_func_value); *part_id= get_part_id_for_sub(loc_part_id, sub_part_id, no_subparts); - DBUG_RETURN(0); + DBUG_RETURN(FALSE); } @@ -3219,36 +3239,43 @@ int get_partition_id_list_sub_linear_key get_partition_id_linear_key_sub */ -uint32 get_partition_id_hash_sub(partition_info *part_info) +int get_partition_id_hash_sub(partition_info *part_info, + uint32 *part_id) { longlong func_value; return get_part_id_hash(part_info->no_subparts, part_info->subpart_expr, - &func_value); + part_id, &func_value); } -uint32 get_partition_id_linear_hash_sub(partition_info *part_info) +int get_partition_id_linear_hash_sub(partition_info *part_info, + uint32 *part_id) { longlong func_value; return get_part_id_linear_hash(part_info, part_info->no_subparts, - part_info->subpart_expr, &func_value); + part_info->subpart_expr, part_id, + &func_value); } -uint32 get_partition_id_key_sub(partition_info *part_info) +int get_partition_id_key_sub(partition_info *part_info, + uint32 *part_id) { longlong func_value; - return get_part_id_key(part_info->subpart_field_array, - part_info->no_subparts, &func_value); + *part_id= get_part_id_key(part_info->subpart_field_array, + part_info->no_subparts, &func_value); + return FALSE; } -uint32 get_partition_id_linear_key_sub(partition_info *part_info) +int get_partition_id_linear_key_sub(partition_info *part_info, + uint32 *part_id) { longlong func_value; - return get_part_id_linear_key(part_info, - part_info->subpart_field_array, - part_info->no_subparts, &func_value); + *part_id= get_part_id_linear_key(part_info, + part_info->subpart_field_array, + part_info->no_subparts, &func_value); + return FALSE; } @@ -3337,37 +3364,39 @@ static bool check_part_func_bound(Field buf A buffer that can be used to evaluate the partition function key_info The index object key_spec A key_range containing key and key length + out:part_id The returned partition id RETURN VALUES - part_id Subpartition id to use + TRUE All fields in partition function are set + FALSE Not all fields in partition function are set + DESCRIPTION Use key buffer to set-up record in buf, move field pointers and get the partition identity and restore field pointers afterwards. */ -static uint32 get_sub_part_id_from_key(const TABLE *table,uchar *buf, - KEY *key_info, - const key_range *key_spec) +static int get_sub_part_id_from_key(const TABLE *table,uchar *buf, + KEY *key_info, + const key_range *key_spec, + uint32 *part_id) { uchar *rec0= table->record[0]; partition_info *part_info= table->part_info; - uint32 part_id; + int res; DBUG_ENTER("get_sub_part_id_from_key"); key_restore(buf, (uchar*)key_spec->key, key_info, key_spec->length); if (likely(rec0 == buf)) - { - part_id= part_info->get_subpartition_id(part_info); - } + res= part_info->get_subpartition_id(part_info, part_id); else { Field **part_field_array= part_info->subpart_field_array; set_field_ptr(part_field_array, buf, rec0); - part_id= part_info->get_subpartition_id(part_info); + res= part_info->get_subpartition_id(part_info, part_id); set_field_ptr(part_field_array, rec0, buf); } - DBUG_RETURN(part_id); + DBUG_RETURN(res); } /* @@ -3586,7 +3615,13 @@ void get_partition_set(const TABLE *tabl else if (part_info->is_sub_partitioned()) { if (part_info->all_fields_in_SPF.is_set(index)) - sub_part= get_sub_part_id_from_key(table, buf, key_info, key_spec); + { + if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part)) + { + part_spec->start_part= no_parts; + DBUG_VOID_RETURN; + } + } else if (part_info->all_fields_in_PPF.is_set(index)) { if (get_part_id_from_key(table,buf,key_info, @@ -3632,7 +3667,14 @@ void get_partition_set(const TABLE *tabl else if (part_info->is_sub_partitioned()) { if (check_part_func_bound(part_info->subpart_field_array)) - sub_part= get_sub_part_id_from_key(table, buf, key_info, key_spec); + { + if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part)) + { + part_spec->start_part= no_parts; + clear_indicator_in_key_fields(key_info); + DBUG_VOID_RETURN; + } + } else if (check_part_func_bound(part_info->part_field_array)) { if (get_part_id_from_key(table,buf,key_info,key_spec,&part_part)) @@ -6836,9 +6878,11 @@ int get_part_iter_for_interval_via_walki field->set_null(); if (is_subpart) { - part_id= part_info->get_subpartition_id(part_info); - init_single_partition_iterator(part_id, part_iter); - return 1; /* Ok, iterator initialized */ + if (!part_info->get_subpartition_id(part_info, &part_id)) + { + init_single_partition_iterator(part_id, part_iter); + return 1; /* Ok, iterator initialized */ + } } else { @@ -7007,13 +7051,17 @@ static uint32 get_next_partition_via_wal static uint32 get_next_subpartition_via_walking(PARTITION_ITERATOR *part_iter) { Field *field= part_iter->part_info->subpart_field_array[0]; + uint32 res; if (part_iter->field_vals.cur == part_iter->field_vals.end) { part_iter->field_vals.cur= part_iter->field_vals.start; return NOT_A_PARTITION_ID; } field->store(part_iter->field_vals.cur++, FALSE); - return part_iter->part_info->get_subpartition_id(part_iter->part_info); + if (part_iter->part_info->get_subpartition_id(part_iter->part_info, + &res)) + return NOT_A_PARTITION_ID; + return res; }