List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:August 25 2008 2:58pm
Subject:Re: bzr commit into mysql-5.1 branch (holyfoot:2683) Bug#38083
View as plain text  
Hi,

You are correct that this actually fixes more than the bug, but please
continue with the fix, and also update sql_partition.cc even a bit further:

Update the comment for get_partition_id() (return value is now 0 - OK,
!= 0 Error, part_id is the out parameter)

and when failing a 'get_part_id_func' function, set *part_id=
HA_ERR_NO_PARTITION_FOUND, or in some places use loc_part_id.

Verify consistent return values / parameters for all 'get_part_id_func'
in sql_partition.cc (for example get_partition_id_list does not comply
to the comment for get_partition_id()) It should return 1 and set
*part_id to HA_ERR_NO_PARTITION_FOUND in 'notfound' label.

remove the duplicate declaration of get_partition_id_list in ha_partition.cc

I have also some proposals below.

Regards
Mattias


Alexey Botchkov wrote:
> #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
>       
OK

>       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;
UPPER CASE on 'set' -> 'SET'
> +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;
> 
UPPER CASE on 'set' -> 'SET'

> === 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());
Why not (so *part_id will not be a valid number):
if (current_thd->is_error())
{
   *part_id= HA_ERR_NO_PARTITION_FOUND;
   DBUG_RETURN(1);
}
*part_id= int_hash_id < 0 ? (uint32) -int_hash_id : (uint32) int_hash_id;
DBUG_RETURN(0);

>  }
>  
>  
> @@ -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())

Set *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);
>  }
>  
>  
> @@ -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);
Why not continue to check for errors here? and if error return
HA_ERR_NO_PARTITION_FOUND.
> +  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);
Too long line!
Check error message (see above).
> +  return part_id;
>  }
>  
>  
> 
> 

-- 
Mattias Jonsson
MySQL Software Engineer
Sun Microsystems
www.sun.com, www.mysql.com
Phone: +46 70 245 91 51

Thread
bzr commit into mysql-5.1 branch (holyfoot:2683) Bug#38083Alexey Botchkov5 Aug
  • Re: bzr commit into mysql-5.1 branch (holyfoot:2683) Bug#38083Mattias Jonsson25 Aug