Commit 6cb8e391 authored by reggie@linux.site's avatar reggie@linux.site

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

BUG# 17430 Partitions: crash on SELECT * FROM t1 WHERE f_int1 IS NULL
parent 79c9ba9e
...@@ -315,4 +315,37 @@ drop table t1; ...@@ -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)); 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)); alter table t1 add partition (partition x3 values in (30));
drop table t1; 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 End of 5.1 tests
...@@ -408,4 +408,44 @@ create table t1 (s1 int, unique (s1)) partition by list (s1) (partition x1 VALUE ...@@ -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)); alter table t1 add partition (partition x3 values in (30));
drop table t1; 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 --echo End of 5.1 tests
...@@ -2341,6 +2341,29 @@ bool partition_key_modified(TABLE *table, List<Item> &fields) ...@@ -2341,6 +2341,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. 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 A handler sets up a variable that corresponds to one of these functions
...@@ -2437,7 +2460,7 @@ static uint32 get_part_id_hash(uint no_parts, ...@@ -2437,7 +2460,7 @@ static uint32 get_part_id_hash(uint no_parts,
longlong *func_value) longlong *func_value)
{ {
DBUG_ENTER("get_part_id_hash"); 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; longlong int_hash_id= *func_value % no_parts;
DBUG_RETURN(int_hash_id < 0 ? -int_hash_id : int_hash_id); DBUG_RETURN(int_hash_id < 0 ? -int_hash_id : int_hash_id);
} }
...@@ -2466,7 +2489,7 @@ static uint32 get_part_id_linear_hash(partition_info *part_info, ...@@ -2466,7 +2489,7 @@ static uint32 get_part_id_linear_hash(partition_info *part_info,
{ {
DBUG_ENTER("get_part_id_linear_hash"); 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, DBUG_RETURN(get_part_id_from_linear_hash(*func_value,
part_info->linear_hash_mask, part_info->linear_hash_mask,
no_parts)); no_parts));
...@@ -2604,7 +2627,7 @@ int get_partition_id_list(partition_info *part_info, ...@@ -2604,7 +2627,7 @@ int get_partition_id_list(partition_info *part_info,
longlong list_value; longlong list_value;
int min_list_index= 0; int min_list_index= 0;
int max_list_index= part_info->no_list_values - 1; 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"); DBUG_ENTER("get_partition_id_list");
*func_value= part_func_value; *func_value= part_func_value;
...@@ -2680,7 +2703,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, ...@@ -2680,7 +2703,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
longlong list_value; longlong list_value;
uint min_list_index= 0, max_list_index= part_info->no_list_values - 1; uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
/* Get the partitioning function value for the endpoint */ /* 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) while (max_list_index >= min_list_index)
{ {
list_index= (max_list_index + min_list_index) >> 1; list_index= (max_list_index + min_list_index) >> 1;
...@@ -2714,7 +2737,7 @@ int get_partition_id_range(partition_info *part_info, ...@@ -2714,7 +2737,7 @@ int get_partition_id_range(partition_info *part_info,
uint min_part_id= 0; uint min_part_id= 0;
uint max_part_id= max_partition; uint max_part_id= max_partition;
uint loc_part_id; 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"); DBUG_ENTER("get_partition_id_int_range");
while (max_part_id > min_part_id) while (max_part_id > min_part_id)
...@@ -2789,7 +2812,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, ...@@ -2789,7 +2812,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
uint max_partition= part_info->no_parts - 1; uint max_partition= part_info->no_parts - 1;
uint min_part_id= 0, max_part_id= max_partition, loc_part_id; uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
/* Get the partitioning function value for the endpoint */ /* 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) while (max_part_id > min_part_id)
{ {
loc_part_id= (max_part_id + min_part_id + 1) >> 1; loc_part_id= (max_part_id + min_part_id + 1) >> 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment