BUG#16002: Handle unsigned integer partition functions

parent c9493421
drop table if exists t1; drop table if exists t1;
create table t1 (a bigint unsigned); create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
ERROR 42000: VALUES value must be of same type as partition function near '),
partition p1 values less than (10))' at line 3
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
partition p1 values in (10));
ERROR 42000: VALUES value must be of same type as partition function near '),
partition p1 values in (10))' at line 3
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (100),
partition p1 values less than MAXVALUE);
insert into t1 values (1);
drop table t1;
create table t1 (a bigint unsigned)
partition by hash (a);
insert into t1 values (0xFFFFFFFFFFFFFFFD); insert into t1 values (0xFFFFFFFFFFFFFFFD);
insert into t1 values (0xFFFFFFFFFFFFFFFE); insert into t1 values (0xFFFFFFFFFFFFFFFE);
select * from t1 where (a + 1) < 10; select * from t1 where (a + 1) < 10;
...@@ -852,7 +871,7 @@ DROP TABLE t1; ...@@ -852,7 +871,7 @@ DROP TABLE t1;
create table t1 (a bigint unsigned) create table t1 (a bigint unsigned)
partition by list (a) partition by list (a)
(partition p0 values in (0-1)); (partition p0 values in (0-1));
ERROR HY000: Partition function is unsigned, cannot have negative constants ERROR HY000: Partition constant is out of partition function domain
create table t1 (a bigint unsigned) create table t1 (a bigint unsigned)
partition by range (a) partition by range (a)
(partition p0 values less than (10)); (partition p0 values less than (10));
......
...@@ -557,4 +557,4 @@ drop table t1; ...@@ -557,4 +557,4 @@ drop table t1;
create table t1 (a bigint unsigned) create table t1 (a bigint unsigned)
partition by range (a) partition by range (a)
(partition p0 values less than (-1)); (partition p0 values less than (-1));
ERROR HY000: Partition function is unsigned, cannot have negative constants ERROR HY000: Partition constant is out of partition function domain
...@@ -9,7 +9,29 @@ ...@@ -9,7 +9,29 @@
drop table if exists t1; drop table if exists t1;
--enable_warnings --enable_warnings
create table t1 (a bigint unsigned); #
# BUG 16002: Handle unsigned integer functions properly
#
--error 1064
create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
--error 1064
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
partition p1 values in (10));
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (100),
partition p1 values less than MAXVALUE);
insert into t1 values (1);
drop table t1;
create table t1 (a bigint unsigned)
partition by hash (a);
insert into t1 values (0xFFFFFFFFFFFFFFFD); insert into t1 values (0xFFFFFFFFFFFFFFFD);
insert into t1 values (0xFFFFFFFFFFFFFFFE); insert into t1 values (0xFFFFFFFFFFFFFFFE);
select * from t1 where (a + 1) < 10; select * from t1 where (a + 1) < 10;
...@@ -966,7 +988,7 @@ DROP TABLE t1; ...@@ -966,7 +988,7 @@ DROP TABLE t1;
# #
#BUG 16002 Erroneus handling of unsigned partition functions #BUG 16002 Erroneus handling of unsigned partition functions
# #
--error ER_SIGNED_PARTITION_CONSTANT_ERROR --error ER_PARTITION_CONST_DOMAIN_ERROR
create table t1 (a bigint unsigned) create table t1 (a bigint unsigned)
partition by list (a) partition by list (a)
(partition p0 values in (0-1)); (partition p0 values in (0-1));
...@@ -978,6 +1000,8 @@ partition by range (a) ...@@ -978,6 +1000,8 @@ partition by range (a)
--error ER_NO_PARTITION_FOR_GIVEN_VALUE --error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (0xFFFFFFFFFFFFFFFF); insert into t1 values (0xFFFFFFFFFFFFFFFF);
drop table t1;
# #
#BUG 18750 Problems with partition names #BUG 18750 Problems with partition names
# #
......
...@@ -748,7 +748,7 @@ CREATE TABLE t1(a int) ...@@ -748,7 +748,7 @@ CREATE TABLE t1(a int)
insert into t1 values (10); insert into t1 values (10);
drop table t1; drop table t1;
--error ER_SIGNED_PARTITION_CONSTANT_ERROR --error ER_PARTITION_CONST_DOMAIN_ERROR
create table t1 (a bigint unsigned) create table t1 (a bigint unsigned)
partition by range (a) partition by range (a)
(partition p0 values less than (-1)); (partition p0 values less than (-1));
...@@ -5162,17 +5162,14 @@ void ha_partition::print_error(int error, myf errflag) ...@@ -5162,17 +5162,14 @@ void ha_partition::print_error(int error, myf errflag)
{ {
char buf[100]; char buf[100];
longlong value= m_part_info->part_expr->val_int(); longlong value= m_part_info->part_expr->val_int();
if (!m_part_info->part_expr->unsigned_flag || if (m_part_info->part_expr->null_value)
m_part_info->part_expr->null_value)
{ {
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),"NULL");
m_part_info->part_expr->null_value ? "NULL" :
llstr(m_part_info->part_expr->val_int(), buf));
} }
else else
{ {
ulonglong value= m_part_info->part_expr->val_int(); longlong2str(value, buf,
longlong2str(value, buf, 10); m_part_info->part_expr->unsigned_flag ? 10 : -10);
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf); my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf);
} }
} }
......
...@@ -36,6 +36,13 @@ enum partition_state { ...@@ -36,6 +36,13 @@ enum partition_state {
PART_IS_ADDED= 8 PART_IS_ADDED= 8
}; };
/*
This struct is used to contain the value of an element
in the VALUES IN struct. It needs to keep knowledge of
whether it is a signed/unsigned value and whether it is
NULL or not.
*/
typedef struct p_elem_val typedef struct p_elem_val
{ {
longlong value; longlong value;
...@@ -59,8 +66,8 @@ class partition_element :public Sql_alloc { ...@@ -59,8 +66,8 @@ class partition_element :public Sql_alloc {
enum partition_state part_state; enum partition_state part_state;
uint16 nodegroup_id; uint16 nodegroup_id;
bool has_null_value; bool has_null_value;
bool signed_flag; bool signed_flag;/* Indicate whether this partition uses signed constants */
bool max_value; bool max_value; /* Indicate whether this partition uses MAXVALUE */
partition_element() partition_element()
: part_max_rows(0), part_min_rows(0), range_value(0), : part_max_rows(0), part_min_rows(0), range_value(0),
......
...@@ -485,10 +485,9 @@ bool partition_info::check_range_constants() ...@@ -485,10 +485,9 @@ bool partition_info::check_range_constants()
else else
{ {
ulonglong upart_range_value_int; ulonglong upart_range_value_int;
if ((i != (no_parts - 1)) || !defined_max_value) if ((i == (no_parts - 1)) && defined_max_value)
part_def->range_value= ULONGLONG_MAX;
upart_range_value_int= part_def->range_value; upart_range_value_int= part_def->range_value;
else
upart_range_value_int= ULONGLONG_MAX;
if (likely(current_largest_uint < upart_range_value_int)) if (likely(current_largest_uint < upart_range_value_int))
{ {
current_largest_uint= upart_range_value_int; current_largest_uint= upart_range_value_int;
...@@ -572,7 +571,6 @@ bool partition_info::check_list_constants() ...@@ -572,7 +571,6 @@ bool partition_info::check_list_constants()
uint i; uint i;
uint list_index= 0; uint list_index= 0;
part_elem_value *list_value; part_elem_value *list_value;
bool not_first;
bool result= TRUE; bool result= TRUE;
longlong curr_value, prev_value; longlong curr_value, prev_value;
partition_element* part_def; partition_element* part_def;
...@@ -638,6 +636,7 @@ bool partition_info::check_list_constants() ...@@ -638,6 +636,7 @@ bool partition_info::check_list_constants()
if (fixed) if (fixed)
{ {
bool first= TRUE;
if (!part_expr->unsigned_flag) if (!part_expr->unsigned_flag)
qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
&list_part_cmp); &list_part_cmp);
...@@ -645,15 +644,14 @@ bool partition_info::check_list_constants() ...@@ -645,15 +644,14 @@ bool partition_info::check_list_constants()
qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
&list_part_cmp_unsigned); &list_part_cmp_unsigned);
not_first= FALSE;
i= prev_value= 0; //prev_value initialised to quiet compiler i= prev_value= 0; //prev_value initialised to quiet compiler
do do
{ {
curr_value= list_array[i].list_value; curr_value= list_array[i].list_value;
if (likely(!not_first || prev_value != curr_value)) if (likely(first || prev_value != curr_value))
{ {
prev_value= curr_value; prev_value= curr_value;
not_first= TRUE; first= FALSE;
} }
else else
{ {
......
...@@ -5826,9 +5826,9 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT ...@@ -5826,9 +5826,9 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT
eng "The NDB cluster engine does not support changing the binlog format on the fly yet" eng "The NDB cluster engine does not support changing the binlog format on the fly yet"
ER_PARTITION_NO_TEMPORARY ER_PARTITION_NO_TEMPORARY
eng "Cannot create temporary table with partitions" eng "Cannot create temporary table with partitions"
ER_SIGNED_PARTITION_CONSTANT_ERROR ER_PARTITION_CONST_DOMAIN_ERROR
eng "Partition function is unsigned, cannot have negative constants" eng "Partition constant is out of partition function domain"
swe "Partitionsfunktionen r positiv, kan inte ha negativa konstanter" swe "Partitionskonstanten r utanfr partitioneringsfunktionens domn"
ER_NULL_IN_VALUES_LESS_THAN ER_NULL_IN_VALUES_LESS_THAN
eng "Not allowed to use NULL value in VALUES LESS THAN" eng "Not allowed to use NULL value in VALUES LESS THAN"
swe "Det r inte tilltet att anvnda NULL-vrden i VALUES LESS THAN" swe "Det r inte tilltet att anvnda NULL-vrden i VALUES LESS THAN"
......
...@@ -819,8 +819,8 @@ int check_signed_flag(partition_info *part_info) ...@@ -819,8 +819,8 @@ int check_signed_flag(partition_info *part_info)
if (part_elem->signed_flag) if (part_elem->signed_flag)
{ {
my_error(ER_SIGNED_PARTITION_CONSTANT_ERROR, MYF(0)); my_error(ER_PARTITION_CONST_DOMAIN_ERROR, MYF(0));
error= ER_SIGNED_PARTITION_CONSTANT_ERROR; error= ER_PARTITION_CONST_DOMAIN_ERROR;
break; break;
} }
} while (++i < part_info->no_parts); } while (++i < part_info->no_parts);
...@@ -841,8 +841,8 @@ int check_signed_flag(partition_info *part_info) ...@@ -841,8 +841,8 @@ int check_signed_flag(partition_info *part_info)
func_expr The item tree reference of the partition function func_expr The item tree reference of the partition function
table The table object table The table object
part_info Reference to partitioning data structure part_info Reference to partitioning data structure
sub_part Is the table subpartitioned as well is_sub_part Is the table subpartitioned as well
set_up_fields Flag if we are to set-up field arrays is_field_to_be_setup Flag if we are to set-up field arrays
RETURN VALUE RETURN VALUE
TRUE An error occurred, something was wrong with the TRUE An error occurred, something was wrong with the
...@@ -1376,7 +1376,7 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, ...@@ -1376,7 +1376,7 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask,
fix_partition_func() fix_partition_func()
thd The thread object thd The thread object
table TABLE object for which partition fields are set-up table TABLE object for which partition fields are set-up
create_table_ind Indicator of whether openfrm was called as part of is_create_table_ind Indicator of whether openfrm was called as part of
CREATE or ALTER TABLE CREATE or ALTER TABLE
RETURN VALUE RETURN VALUE
...@@ -1760,29 +1760,18 @@ static int add_partition_values(File fptr, partition_info *part_info, ...@@ -1760,29 +1760,18 @@ static int add_partition_values(File fptr, partition_info *part_info,
if (part_info->part_type == RANGE_PARTITION) if (part_info->part_type == RANGE_PARTITION)
{ {
err+= add_string(fptr, "VALUES LESS THAN "); err+= add_string(fptr, "VALUES LESS THAN ");
if (p_elem->signed_flag)
{
if (!p_elem->max_value) if (!p_elem->max_value)
{ {
err+= add_begin_parenthesis(fptr); err+= add_begin_parenthesis(fptr);
if (p_elem->signed_flag)
err+= add_int(fptr, p_elem->range_value); err+= add_int(fptr, p_elem->range_value);
err+= add_end_parenthesis(fptr);
}
else
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
}
else else
{
if (!p_elem->max_value)
{
err+= add_begin_parenthesis(fptr);
err+= add_uint(fptr, (ulonglong)p_elem->range_value); err+= add_uint(fptr, (ulonglong)p_elem->range_value);
err+= add_end_parenthesis(fptr); err+= add_end_parenthesis(fptr);
} }
else else
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str); err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
} }
}
else if (part_info->part_type == LIST_PARTITION) else if (part_info->part_type == LIST_PARTITION)
{ {
uint i; uint i;
......
...@@ -3697,7 +3697,7 @@ opt_part_values: ...@@ -3697,7 +3697,7 @@ opt_part_values:
; ;
part_func_max: part_func_max:
MAX_VALUE_SYM max_value_sym
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (lex->part_info->defined_max_value) if (lex->part_info->defined_max_value)
...@@ -3724,6 +3724,11 @@ part_func_max: ...@@ -3724,6 +3724,11 @@ part_func_max:
} }
; ;
max_value_sym:
MAX_VALUE_SYM
| '(' MAX_VALUE_SYM ')'
;
part_range_func: part_range_func:
'(' part_bit_expr ')' '(' part_bit_expr ')'
{ {
......
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