Commit a9dab911 authored by unknown's avatar unknown
Browse files

BUG# 17430 Partitoins: crash on SELECT * FROM t1 WHERE f_int1 IS NULL

BUG# 17432: Partitions: wrong result, SELECT ... WHERE <column> is null


mysql-test/r/partition.result:
  result block for tests
mysql-test/t/partition.test:
  test cases for bug #17432 and 17430
sql/sql_partition.cc:
  improve null handling by returning LONGLONG_MIN for values that are NULL
parent 3a78156e
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -315,4 +315,37 @@ drop table t1;
create table t1 (s1 int, unique (s1)) partition by list (s1) (partition x1 VALUES in (10), partition x2 values in (20));
alter table t1 add partition (partition x3 values in (30));
drop table t1;
CREATE TABLE t1 (
f_int1 INTEGER, f_int2 INTEGER,
f_char1 CHAR(10), f_char2 CHAR(10), f_charbig VARCHAR(1000)
)
PARTITION BY RANGE(f_int1 DIV 2)
SUBPARTITION BY HASH(f_int1)
SUBPARTITIONS 2
(PARTITION parta VALUES LESS THAN (0),
PARTITION partb VALUES LESS THAN (5),
PARTITION parte VALUES LESS THAN (10),
PARTITION partf VALUES LESS THAN (2147483647));
INSERT INTO t1 SET f_int1 = NULL , f_int2 = -20, f_char1 = CAST(-20 AS CHAR),
f_char2 = CAST(-20 AS CHAR), f_charbig = '#NULL#';
SELECT * FROM t1 WHERE f_int1 IS NULL;
f_int1	f_int2	f_char1	f_char2	f_charbig
NULL	-20	-20	-20	#NULL#
SELECT * FROM t1;
f_int1	f_int2	f_char1	f_char2	f_charbig
NULL	-20	-20	-20	#NULL#
drop table t1;
CREATE TABLE t1 (
f_int1 INTEGER, f_int2 INTEGER,
f_char1 CHAR(10), f_char2 CHAR(10), f_charbig VARCHAR(1000)  )
PARTITION BY LIST(MOD(f_int1,2))
SUBPARTITION BY KEY(f_int1)
(PARTITION part1 VALUES IN (-1) (SUBPARTITION sp1, SUBPARTITION sp2),
PARTITION part2 VALUES IN (0) (SUBPARTITION sp3, SUBPARTITION sp5),
PARTITION part3 VALUES IN (1) (SUBPARTITION sp4, SUBPARTITION sp6));
INSERT INTO t1 SET f_int1 = 2, f_int2 = 2, f_char1 = '2', f_char2 = '2', f_charbig = '===2===';
INSERT INTO t1 SET f_int1 = 2, f_int2 = 2, f_char1 = '2', f_char2 = '2', f_charbig = '===2===';
SELECT * FROM t1 WHERE f_int1  IS NULL;
f_int1	f_int2	f_char1	f_char2	f_charbig
drop table t1;
End of 5.1 tests
+40 −0
Original line number Diff line number Diff line
@@ -408,4 +408,44 @@ create table t1 (s1 int, unique (s1)) partition by list (s1) (partition x1 VALUE
alter table t1 add partition (partition x3 values in (30));
drop table t1;

#
# Bug #17432: Partition functions containing NULL values should return
#             LONGLONG_MIN
#
CREATE TABLE t1 (
 f_int1 INTEGER, f_int2 INTEGER,
 f_char1 CHAR(10), f_char2 CHAR(10), f_charbig VARCHAR(1000)
 )
 PARTITION BY RANGE(f_int1 DIV 2)
 SUBPARTITION BY HASH(f_int1)
 SUBPARTITIONS 2
 (PARTITION parta VALUES LESS THAN (0),
  PARTITION partb VALUES LESS THAN (5),
  PARTITION parte VALUES LESS THAN (10),
  PARTITION partf VALUES LESS THAN (2147483647));
INSERT INTO t1 SET f_int1 = NULL , f_int2 = -20, f_char1 = CAST(-20 AS CHAR),
                   f_char2 = CAST(-20 AS CHAR), f_charbig = '#NULL#';
SELECT * FROM t1 WHERE f_int1 IS NULL;
SELECT * FROM t1;
drop table t1;

#
# Bug 17430: Crash when SELECT * from t1 where field IS NULL
#

CREATE TABLE t1 (
 f_int1 INTEGER, f_int2 INTEGER,
 f_char1 CHAR(10), f_char2 CHAR(10), f_charbig VARCHAR(1000)  )
 PARTITION BY LIST(MOD(f_int1,2))
 SUBPARTITION BY KEY(f_int1)
 (PARTITION part1 VALUES IN (-1) (SUBPARTITION sp1, SUBPARTITION sp2),
  PARTITION part2 VALUES IN (0) (SUBPARTITION sp3, SUBPARTITION sp5),
  PARTITION part3 VALUES IN (1) (SUBPARTITION sp4, SUBPARTITION sp6));

INSERT INTO t1 SET f_int1 = 2, f_int2 = 2, f_char1 = '2', f_char2 = '2', f_charbig = '===2===';
INSERT INTO t1 SET f_int1 = 2, f_int2 = 2, f_char1 = '2', f_char2 = '2', f_charbig = '===2===';

SELECT * FROM t1 WHERE f_int1  IS NULL;
drop table t1;

--echo End of 5.1 tests
+29 −6
Original line number Diff line number Diff line
@@ -2629,6 +2629,29 @@ bool partition_key_modified(TABLE *table, List<Item> &fields)
}


/*
  A function to handle correct handling of NULL values in partition
  functions.
  SYNOPSIS
    part_val_int()
    item_expr                 The item expression to evaluate
  RETURN VALUES
    The value of the partition function, LONGLONG_MIN if any null value
    in function
*/

static
inline
longlong
part_val_int(Item *item_expr)
{
  longlong value= item_expr->val_int();
  if (item_expr->null_value)
    value= LONGLONG_MIN;
  return value;
}


/*
  The next set of functions are used to calculate the partition identity.
  A handler sets up a variable that corresponds to one of these functions
@@ -2725,7 +2748,7 @@ static uint32 get_part_id_hash(uint no_parts,
                               longlong *func_value)
{
  DBUG_ENTER("get_part_id_hash");
  *func_value= part_expr->val_int();
  *func_value= part_val_int(part_expr);
  longlong int_hash_id= *func_value % no_parts;
  DBUG_RETURN(int_hash_id < 0 ? -int_hash_id : int_hash_id);
}
@@ -2754,7 +2777,7 @@ static uint32 get_part_id_linear_hash(partition_info *part_info,
{
  DBUG_ENTER("get_part_id_linear_hash");

  *func_value= part_expr->val_int();
  *func_value= part_val_int(part_expr);
  DBUG_RETURN(get_part_id_from_linear_hash(*func_value,
                                           part_info->linear_hash_mask,
                                           no_parts));
@@ -2892,7 +2915,7 @@ int get_partition_id_list(partition_info *part_info,
  longlong list_value;
  int min_list_index= 0;
  int max_list_index= part_info->no_list_values - 1;
  longlong part_func_value= part_info->part_expr->val_int();
  longlong part_func_value= part_val_int(part_info->part_expr);
  DBUG_ENTER("get_partition_id_list");

  *func_value= part_func_value;
@@ -2968,7 +2991,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
  longlong list_value;
  uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
  /* Get the partitioning function value for the endpoint */
  longlong part_func_value= part_info->part_expr->val_int();
  longlong part_func_value= part_val_int(part_info->part_expr);
  while (max_list_index >= min_list_index)
  {
    list_index= (max_list_index + min_list_index) >> 1;
@@ -3002,7 +3025,7 @@ int get_partition_id_range(partition_info *part_info,
  uint min_part_id= 0;
  uint max_part_id= max_partition;
  uint loc_part_id;
  longlong part_func_value= part_info->part_expr->val_int();
  longlong part_func_value= part_val_int(part_info->part_expr);
  DBUG_ENTER("get_partition_id_int_range");

  while (max_part_id > min_part_id)
@@ -3077,7 +3100,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
  uint max_partition= part_info->no_parts - 1;
  uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
  /* Get the partitioning function value for the endpoint */
  longlong part_func_value= part_info->part_expr->val_int();
  longlong part_func_value= part_val_int(part_info->part_expr);
  while (max_part_id > min_part_id)
  {
    loc_part_id= (max_part_id + min_part_id + 1) >> 1;