summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ndb_partition_error.result9
-rw-r--r--mysql-test/r/partition.result49
-rw-r--r--mysql-test/t/ndb_partition_error.test13
-rw-r--r--mysql-test/t/partition.test57
-rw-r--r--sql/ha_ndbcluster.cc1
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/partition_element.h3
-rw-r--r--sql/partition_info.h7
-rw-r--r--sql/sql_partition.cc41
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_yacc.yy46
11 files changed, 221 insertions, 12 deletions
diff --git a/mysql-test/r/ndb_partition_error.result b/mysql-test/r/ndb_partition_error.result
index 66f623dee13..d86dc382185 100644
--- a/mysql-test/r/ndb_partition_error.result
+++ b/mysql-test/r/ndb_partition_error.result
@@ -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;
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index cd333cc5fb4..59e29046d90 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -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
diff --git a/mysql-test/t/ndb_partition_error.test b/mysql-test/t/ndb_partition_error.test
index c84266b66f7..b2b6017ce7b 100644
--- a/mysql-test/t/ndb_partition_error.test
+++ b/mysql-test/t/ndb_partition_error.test
@@ -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;
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index 47c25652ae9..f22edb54756 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -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
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index ff8a1221052..7f1eb343139 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -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
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e7a324481db..927b5a4a065 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -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
diff --git a/sql/partition_element.h b/sql/partition_element.h
index 8a11c332897..d20715d2408 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -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();
diff --git a/sql/partition_info.h b/sql/partition_info.h
index c8cb4ae407a..4a00f5c889f 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -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();
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index c98f8f915b9..257c1988cbd 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -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;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 13f880ef228..51c92977a27 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6c8b52d243c..235e78c6657 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
}
;