From e05d2d06cb4adfe27dc4c0c4cb8f445332e9ab80 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 Jun 2006 14:55:22 -0400 Subject: [PATCH] BUG#16002: Handle unsigned integer partition functions mysql-test/r/partition.result: Added new test cases mysql-test/r/partition_error.result: Fixed test case mysql-test/t/partition.test: Added new test cases mysql-test/t/partition_error.test: Fixed test case sql/ha_partition.cc: Review fixes sql/partition_element.h: Review fixes sql/partition_info.cc: Review fixes sql/share/errmsg.txt: Review fixes sql/sql_partition.cc: Review fixes sql/sql_yacc.yy: Enabled possibility to use (MAXVALUE) as well as MAXVALUE. --- mysql-test/r/partition.result | 23 ++++++++++++++++++-- mysql-test/r/partition_error.result | 2 +- mysql-test/t/partition.test | 28 ++++++++++++++++++++++-- mysql-test/t/partition_error.test | 2 +- sql/ha_partition.cc | 11 ++++------ sql/partition_element.h | 11 ++++++++-- sql/partition_info.cc | 14 ++++++------ sql/share/errmsg.txt | 6 +++--- sql/sql_partition.cc | 33 ++++++++++------------------- sql/sql_yacc.yy | 7 +++++- 10 files changed, 88 insertions(+), 49 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index b76896f720f..50570894a51 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,5 +1,24 @@ 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 (0xFFFFFFFFFFFFFFFE); select * from t1 where (a + 1) < 10; @@ -852,7 +871,7 @@ DROP TABLE t1; create table t1 (a bigint unsigned) partition by list (a) (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) partition by range (a) (partition p0 values less than (10)); diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index cc51b909c51..1295eba16ae 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -557,4 +557,4 @@ drop table t1; create table t1 (a bigint unsigned) partition by range (a) (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 diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 3714a4a3346..b57fc6420f0 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -9,7 +9,29 @@ drop table if exists t1; --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 (0xFFFFFFFFFFFFFFFE); select * from t1 where (a + 1) < 10; @@ -966,7 +988,7 @@ DROP TABLE t1; # #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) partition by list (a) (partition p0 values in (0-1)); @@ -978,6 +1000,8 @@ partition by range (a) --error ER_NO_PARTITION_FOR_GIVEN_VALUE insert into t1 values (0xFFFFFFFFFFFFFFFF); +drop table t1; + # #BUG 18750 Problems with partition names # diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index dad2d2beda6..35aef969ad6 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -748,7 +748,7 @@ CREATE TABLE t1(a int) insert into t1 values (10); drop table t1; ---error ER_SIGNED_PARTITION_CONSTANT_ERROR +--error ER_PARTITION_CONST_DOMAIN_ERROR create table t1 (a bigint unsigned) partition by range (a) (partition p0 values less than (-1)); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 3014c0317be..bedda6b4fe7 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5162,17 +5162,14 @@ void ha_partition::print_error(int error, myf errflag) { char buf[100]; longlong value= m_part_info->part_expr->val_int(); - if (!m_part_info->part_expr->unsigned_flag || - m_part_info->part_expr->null_value) + if (m_part_info->part_expr->null_value) { - 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)); + my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),"NULL"); } else { - ulonglong value= m_part_info->part_expr->val_int(); - longlong2str(value, buf, 10); + longlong2str(value, buf, + m_part_info->part_expr->unsigned_flag ? 10 : -10); my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf); } } diff --git a/sql/partition_element.h b/sql/partition_element.h index 7063e514901..7818c25c2f6 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -36,6 +36,13 @@ enum partition_state { 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 { longlong value; @@ -59,8 +66,8 @@ public: enum partition_state part_state; uint16 nodegroup_id; bool has_null_value; - bool signed_flag; - bool max_value; + bool signed_flag;/* Indicate whether this partition uses signed constants */ + bool max_value; /* Indicate whether this partition uses MAXVALUE */ partition_element() : part_max_rows(0), part_min_rows(0), range_value(0), diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 97cac37c00e..a6ca1e0107e 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -485,10 +485,9 @@ bool partition_info::check_range_constants() else { ulonglong upart_range_value_int; - if ((i != (no_parts - 1)) || !defined_max_value) - upart_range_value_int= part_def->range_value; - else - upart_range_value_int= ULONGLONG_MAX; + if ((i == (no_parts - 1)) && defined_max_value) + part_def->range_value= ULONGLONG_MAX; + upart_range_value_int= part_def->range_value; if (likely(current_largest_uint < upart_range_value_int)) { current_largest_uint= upart_range_value_int; @@ -572,7 +571,6 @@ bool partition_info::check_list_constants() uint i; uint list_index= 0; part_elem_value *list_value; - bool not_first; bool result= TRUE; longlong curr_value, prev_value; partition_element* part_def; @@ -638,6 +636,7 @@ bool partition_info::check_list_constants() if (fixed) { + bool first= TRUE; if (!part_expr->unsigned_flag) qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), &list_part_cmp); @@ -645,15 +644,14 @@ bool partition_info::check_list_constants() qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), &list_part_cmp_unsigned); - not_first= FALSE; i= prev_value= 0; //prev_value initialised to quiet compiler do { 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; - not_first= TRUE; + first= FALSE; } else { diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 203f58ba108..148a4402ccd 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -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" ER_PARTITION_NO_TEMPORARY eng "Cannot create temporary table with partitions" -ER_SIGNED_PARTITION_CONSTANT_ERROR - eng "Partition function is unsigned, cannot have negative constants" - swe "Partitionsfunktionen är positiv, kan inte ha negativa konstanter" +ER_PARTITION_CONST_DOMAIN_ERROR + eng "Partition constant is out of partition function domain" + swe "Partitionskonstanten är utanför partitioneringsfunktionens domän" ER_NULL_IN_VALUES_LESS_THAN eng "Not allowed to use NULL value in VALUES LESS THAN" swe "Det är inte tillåtet att använda NULL-värden i VALUES LESS THAN" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 05f99110f61..45cd13ce854 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -819,8 +819,8 @@ int check_signed_flag(partition_info *part_info) if (part_elem->signed_flag) { - my_error(ER_SIGNED_PARTITION_CONSTANT_ERROR, MYF(0)); - error= ER_SIGNED_PARTITION_CONSTANT_ERROR; + my_error(ER_PARTITION_CONST_DOMAIN_ERROR, MYF(0)); + error= ER_PARTITION_CONST_DOMAIN_ERROR; break; } } while (++i < part_info->no_parts); @@ -841,8 +841,8 @@ int check_signed_flag(partition_info *part_info) func_expr The item tree reference of the partition function table The table object part_info Reference to partitioning data structure - sub_part Is the table subpartitioned as well - set_up_fields Flag if we are to set-up field arrays + is_sub_part Is the table subpartitioned as well + is_field_to_be_setup Flag if we are to set-up field arrays RETURN VALUE 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, fix_partition_func() thd The thread object 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 RETURN VALUE @@ -1760,28 +1760,17 @@ static int add_partition_values(File fptr, partition_info *part_info, if (part_info->part_type == RANGE_PARTITION) { 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_end_parenthesis(fptr); - } else - err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str); + err+= add_uint(fptr, (ulonglong)p_elem->range_value); + err+= add_end_parenthesis(fptr); } else - { - if (!p_elem->max_value) - { - err+= add_begin_parenthesis(fptr); - err+= add_uint(fptr, (ulonglong)p_elem->range_value); - err+= add_end_parenthesis(fptr); - } - 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) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9e2fa96fec7..0fcb80c0d79 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3697,7 +3697,7 @@ opt_part_values: ; part_func_max: - MAX_VALUE_SYM + max_value_sym { LEX *lex= Lex; if (lex->part_info->defined_max_value) @@ -3724,6 +3724,11 @@ part_func_max: } ; +max_value_sym: + MAX_VALUE_SYM + | '(' MAX_VALUE_SYM ')' + ; + part_range_func: '(' part_bit_expr ')' {