Fix for bug#15447 Partitions: NULL is treated as zero
NULL value handling mysql-test/r/ndb_partition_error.result: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/r/partition.result: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/t/ndb_partition_error.test: Fix for bug#15447 Partitions: NULL is treated as zero test case mysql-test/t/partition.test: Fix for bug#15447 Partitions: NULL is treated as zero test case sql/partition_element.h: Fix for bug#15447 Partitions: NULL is treated as zero added null value flag to partition_element object sql/partition_info.h: Fix for bug#15447 Partitions: NULL is treated as zero added null value flag to partition_info object added has_null partition id variable
This commit is contained in:
parent
8cf8e4ed37
commit
807c7a6a49
@ -36,3 +36,12 @@ INSERT INTO t1 VALUES (2);
|
||||
UPDATE t1 SET id=5 WHERE id=2;
|
||||
ERROR HY000: Table has no partition for value 5
|
||||
DROP TABLE t1;
|
||||
create table t1 (a int,b int, c int)
|
||||
engine = ndb
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (5, 1));
|
||||
insert into t1 values (NULL,1,1);
|
||||
ERROR HY000: Table has no partition for value NULL
|
||||
drop table t1;
|
||||
|
@ -373,4 +373,53 @@ end//
|
||||
call p()//
|
||||
drop procedure p//
|
||||
drop table t1//
|
||||
create table t1 (a int,b int,c int,key(a,b))
|
||||
partition by range (a)
|
||||
partitions 3
|
||||
(partition x1 values less than (0) tablespace ts1,
|
||||
partition x2 values less than (10) tablespace ts2,
|
||||
partition x3 values less than maxvalue tablespace ts3);
|
||||
insert into t1 values (NULL, 1, 1);
|
||||
insert into t1 values (0, 1, 1);
|
||||
insert into t1 values (12, 1, 1);
|
||||
select partition_name, partition_description, table_rows
|
||||
from information_schema.partitions where table_schema ='test';
|
||||
partition_name partition_description table_rows
|
||||
x1 0 1
|
||||
x2 10 1
|
||||
x3 MAXVALUE 1
|
||||
drop table t1;
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11,12),
|
||||
partition x234 values in (1 ,NULL, NULL));
|
||||
ERROR HY000: Multiple definition of same constant in list partitioning
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, NULL),
|
||||
partition x234 values in (1 ,NULL));
|
||||
ERROR HY000: Multiple definition of same constant in list partitioning
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (5, 1));
|
||||
insert into t1 values (NULL,1,1);
|
||||
ERROR HY000: Table has no partition for value NULL
|
||||
drop table t1;
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (NULL, 1));
|
||||
insert into t1 values (11,1,6);
|
||||
insert into t1 values (NULL,1,1);
|
||||
select partition_name, partition_description, table_rows
|
||||
from information_schema.partitions where table_schema ='test';
|
||||
partition_name partition_description table_rows
|
||||
x123 11,12 1
|
||||
x234 NULL,1 1
|
||||
drop table t1;
|
||||
End of 5.1 tests
|
||||
|
@ -56,3 +56,16 @@ INSERT INTO t1 VALUES (2);
|
||||
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
||||
UPDATE t1 SET id=5 WHERE id=2;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# NULL for LIST partition
|
||||
#
|
||||
create table t1 (a int,b int, c int)
|
||||
engine = ndb
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (5, 1));
|
||||
--error 1504
|
||||
insert into t1 values (NULL,1,1);
|
||||
drop table t1;
|
||||
|
@ -483,4 +483,61 @@ drop procedure p//
|
||||
drop table t1//
|
||||
delimiter ;//
|
||||
|
||||
#
|
||||
# Bug #15447 Partitions: NULL is treated as zero
|
||||
#
|
||||
|
||||
# NULL for RANGE partition
|
||||
create table t1 (a int,b int,c int,key(a,b))
|
||||
partition by range (a)
|
||||
partitions 3
|
||||
(partition x1 values less than (0) tablespace ts1,
|
||||
partition x2 values less than (10) tablespace ts2,
|
||||
partition x3 values less than maxvalue tablespace ts3);
|
||||
|
||||
insert into t1 values (NULL, 1, 1);
|
||||
insert into t1 values (0, 1, 1);
|
||||
insert into t1 values (12, 1, 1);
|
||||
|
||||
select partition_name, partition_description, table_rows
|
||||
from information_schema.partitions where table_schema ='test';
|
||||
drop table t1;
|
||||
|
||||
# NULL for LIST partition
|
||||
--error 1473
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11,12),
|
||||
partition x234 values in (1 ,NULL, NULL));
|
||||
|
||||
--error 1473
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, NULL),
|
||||
partition x234 values in (1 ,NULL));
|
||||
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (5, 1));
|
||||
--error 1504
|
||||
insert into t1 values (NULL,1,1);
|
||||
drop table t1;
|
||||
|
||||
create table t1 (a int,b int, c int)
|
||||
partition by list(a)
|
||||
partitions 2
|
||||
(partition x123 values in (11, 12),
|
||||
partition x234 values in (NULL, 1));
|
||||
|
||||
insert into t1 values (11,1,6);
|
||||
insert into t1 values (NULL,1,1);
|
||||
|
||||
select partition_name, partition_description, table_rows
|
||||
from information_schema.partitions where table_schema ='test';
|
||||
drop table t1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
@ -6012,6 +6012,7 @@ void ha_ndbcluster::print_error(int error, myf errflag)
|
||||
{
|
||||
char buf[100];
|
||||
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
||||
m_part_info->part_expr->null_value ? "NULL" :
|
||||
llstr(m_part_info->part_expr->val_int(), buf));
|
||||
}
|
||||
else
|
||||
|
@ -5092,6 +5092,7 @@ void ha_partition::print_error(int error, myf errflag)
|
||||
{
|
||||
char buf[100];
|
||||
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
|
||||
m_part_info->part_expr->null_value ? "NULL" :
|
||||
llstr(m_part_info->part_expr->val_int(), buf));
|
||||
}
|
||||
else
|
||||
|
@ -51,13 +51,14 @@ public:
|
||||
handlerton *engine_type;
|
||||
enum partition_state part_state;
|
||||
uint16 nodegroup_id;
|
||||
bool has_null_value;
|
||||
|
||||
partition_element()
|
||||
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
||||
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
||||
data_file_name(NULL), index_file_name(NULL),
|
||||
engine_type(NULL),part_state(PART_NORMAL),
|
||||
nodegroup_id(UNDEF_NODEGROUP)
|
||||
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE)
|
||||
{
|
||||
subpartitions.empty();
|
||||
list_val_list.empty();
|
||||
|
@ -181,6 +181,9 @@ public:
|
||||
bool linear_hash_ind;
|
||||
bool fixed;
|
||||
bool from_openfrm;
|
||||
bool has_null_value;
|
||||
uint has_null_part_id;
|
||||
|
||||
|
||||
partition_info()
|
||||
: get_partition_id(NULL), get_part_partition_id(NULL),
|
||||
@ -211,7 +214,9 @@ public:
|
||||
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
|
||||
linear_hash_ind(FALSE),
|
||||
fixed(FALSE),
|
||||
from_openfrm(FALSE)
|
||||
from_openfrm(FALSE),
|
||||
has_null_value(FALSE),
|
||||
has_null_part_id(0)
|
||||
{
|
||||
all_fields_in_PF.clear_all();
|
||||
all_fields_in_PPF.clear_all();
|
||||
|
@ -531,6 +531,7 @@ static bool check_list_constants(partition_info *part_info)
|
||||
bool result= TRUE;
|
||||
longlong curr_value, prev_value;
|
||||
partition_element* part_def;
|
||||
bool found_null= FALSE;
|
||||
List_iterator<partition_element> list_func_it(part_info->partitions);
|
||||
DBUG_ENTER("check_list_constants");
|
||||
|
||||
@ -556,6 +557,17 @@ static bool check_list_constants(partition_info *part_info)
|
||||
do
|
||||
{
|
||||
part_def= list_func_it++;
|
||||
if (part_def->has_null_value)
|
||||
{
|
||||
if (found_null)
|
||||
{
|
||||
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
||||
goto end;
|
||||
}
|
||||
part_info->has_null_value= TRUE;
|
||||
part_info->has_null_part_id= i;
|
||||
found_null= TRUE;
|
||||
}
|
||||
List_iterator<longlong> list_val_it1(part_def->list_val_list);
|
||||
while (list_val_it1++)
|
||||
no_list_values++;
|
||||
@ -2041,6 +2053,16 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
||||
err+= add_string(fptr, "VALUES IN ");
|
||||
uint no_items= p_elem->list_val_list.elements;
|
||||
err+= add_begin_parenthesis(fptr);
|
||||
if (p_elem->has_null_value)
|
||||
{
|
||||
err+= add_string(fptr, "NULL");
|
||||
if (no_items == 0)
|
||||
{
|
||||
err+= add_end_parenthesis(fptr);
|
||||
goto end;
|
||||
}
|
||||
err+= add_comma(fptr);
|
||||
}
|
||||
i= 0;
|
||||
do
|
||||
{
|
||||
@ -2051,6 +2073,7 @@ static int add_partition_values(File fptr, partition_info *part_info,
|
||||
} while (++i < no_items);
|
||||
err+= add_end_parenthesis(fptr);
|
||||
}
|
||||
end:
|
||||
return err + add_space(fptr);
|
||||
}
|
||||
|
||||
@ -2631,6 +2654,15 @@ int get_partition_id_list(partition_info *part_info,
|
||||
longlong part_func_value= part_val_int(part_info->part_expr);
|
||||
DBUG_ENTER("get_partition_id_list");
|
||||
|
||||
if (part_info->part_expr->null_value)
|
||||
{
|
||||
if (part_info->has_null_value)
|
||||
{
|
||||
*part_id= part_info->has_null_part_id;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
goto notfound;
|
||||
}
|
||||
*func_value= part_func_value;
|
||||
while (max_list_index >= min_list_index)
|
||||
{
|
||||
@ -2741,6 +2773,11 @@ int get_partition_id_range(partition_info *part_info,
|
||||
longlong part_func_value= part_val_int(part_info->part_expr);
|
||||
DBUG_ENTER("get_partition_id_int_range");
|
||||
|
||||
if (part_info->part_expr->null_value)
|
||||
{
|
||||
*part_id= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
while (max_part_id > min_part_id)
|
||||
{
|
||||
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
||||
@ -2814,6 +2851,10 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
|
||||
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_val_int(part_info->part_expr);
|
||||
|
||||
if (part_info->part_expr->null_value)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
while (max_part_id > min_part_id)
|
||||
{
|
||||
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
||||
|
@ -3832,6 +3832,12 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
|
||||
uint no_items= part_elem->list_val_list.elements;
|
||||
tmp_str.length(0);
|
||||
tmp_res.length(0);
|
||||
if (part_elem->has_null_value)
|
||||
{
|
||||
tmp_str.append("NULL");
|
||||
if (no_items > 0)
|
||||
tmp_str.append(",");
|
||||
}
|
||||
while ((list_value= list_val_it++))
|
||||
{
|
||||
tmp_res.set(*list_value, cs);
|
||||
|
@ -42,6 +42,12 @@
|
||||
#include <myisam.h>
|
||||
#include <myisammrg.h>
|
||||
|
||||
typedef struct p_elem_val
|
||||
{
|
||||
longlong value;
|
||||
bool null_value;
|
||||
} part_elem_value;
|
||||
|
||||
int yylex(void *yylval, void *yythd);
|
||||
|
||||
const LEX_STRING null_lex_str={0,0};
|
||||
@ -105,6 +111,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2)
|
||||
sp_name *spname;
|
||||
struct st_lex *lex;
|
||||
sp_head *sphead;
|
||||
struct p_elem_val *p_elem_value;
|
||||
}
|
||||
|
||||
%{
|
||||
@ -752,7 +759,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%type <ulonglong_number>
|
||||
ulonglong_num size_number
|
||||
|
||||
%type <longlong_number>
|
||||
%type <p_elem_value>
|
||||
part_bit_expr
|
||||
|
||||
%type <lock_type>
|
||||
@ -3781,7 +3788,7 @@ part_func_max:
|
||||
part_range_func:
|
||||
'(' part_bit_expr ')'
|
||||
{
|
||||
Lex->part_info->curr_part_elem->range_value= $2;
|
||||
Lex->part_info->curr_part_elem->range_value= $2->value;
|
||||
}
|
||||
;
|
||||
|
||||
@ -3793,12 +3800,12 @@ part_list_func:
|
||||
part_list_item:
|
||||
part_bit_expr
|
||||
{
|
||||
longlong *value_ptr;
|
||||
if (!(value_ptr= (longlong*)sql_alloc(sizeof(longlong))) ||
|
||||
((*value_ptr= $1, FALSE) ||
|
||||
Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr)))
|
||||
part_elem_value *value_ptr= $1;
|
||||
if (!value_ptr->null_value &&
|
||||
Lex->part_info->curr_part_elem->
|
||||
list_val_list.push_back((longlong*) &value_ptr->value))
|
||||
{
|
||||
mem_alloc_error(sizeof(longlong));
|
||||
mem_alloc_error(sizeof(part_elem_value));
|
||||
YYABORT;
|
||||
}
|
||||
}
|
||||
@ -3818,6 +3825,15 @@ part_bit_expr:
|
||||
|
||||
context->table_list= 0;
|
||||
thd->where= "partition function";
|
||||
|
||||
part_elem_value *value_ptr=
|
||||
(part_elem_value*)sql_alloc(sizeof(part_elem_value));
|
||||
if (!value_ptr)
|
||||
{
|
||||
mem_alloc_error(sizeof(part_elem_value));
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
if (part_expr->fix_fields(YYTHD, (Item**)0) ||
|
||||
((context->table_list= save_list), FALSE) ||
|
||||
(!part_expr->const_item()) ||
|
||||
@ -3827,13 +3843,23 @@ part_bit_expr:
|
||||
YYABORT;
|
||||
}
|
||||
thd->where= save_where;
|
||||
if (part_expr->result_type() != INT_RESULT)
|
||||
value_ptr->value= part_expr->val_int();
|
||||
if ((value_ptr->null_value= part_expr->null_value))
|
||||
{
|
||||
if (Lex->part_info->curr_part_elem->has_null_value)
|
||||
{
|
||||
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
||||
YYABORT;
|
||||
}
|
||||
Lex->part_info->curr_part_elem->has_null_value= TRUE;
|
||||
}
|
||||
else if (part_expr->result_type() != INT_RESULT &&
|
||||
!part_expr->null_value)
|
||||
{
|
||||
yyerror(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR));
|
||||
YYABORT;
|
||||
}
|
||||
item_value= part_expr->val_int();
|
||||
$$= item_value;
|
||||
$$= value_ptr;
|
||||
}
|
||||
;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user