From faa5f3e00754f326eed456b9d7b36be751fd11b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Apr 2006 22:51:34 -0400 Subject: BUG#16002: Make partition functions that are unsigned work properly mysql-test/r/partition.result: A number of new test cases for unsigned partition functions mysql-test/r/partition_error.result: A number of new test cases for unsigned partition functions mysql-test/r/partition_range.result: A number of new test cases for unsigned partition functions mysql-test/t/partition.test: A number of new test cases for unsigned partition functions mysql-test/t/partition_error.test: A number of new test cases for unsigned partition functions mysql-test/t/partition_range.test: A number of new test cases for unsigned partition functions sql/ha_partition.cc: Error message for no partition found needs to take signed/unsigned into account when printing erroneus value sql/partition_element.h: Introduced signed_flag and max_value flag on partition elements Also list is now a list of a struct rather than simply longlong values Small rearranges of order sql/partition_info.cc: Introduced signed_flag and max_value flag on partition elements Also list is now a list of a struct rather than simply longlong values Small rearranges of order Lots of new code to handle checks of proper definition of table when partition function is unsigned sql/partition_info.h: Mostly rearrangement of code and some addition of a THD object in check_partition_info call plus a new method for comparing unsigned values sql/share/errmsg.txt: Negative values not ok for unsigned partition functions sql/sql_partition.cc: Fixed a multi-thread bug (when defining several partitioned tables in parallel) New code to generate partition syntax that takes into account sign of constants. Made function fix_fields_part_func more reusable. Fixed a number of get_partition_id functions for range and list and similar functions for partition pruning code. Unfortunately fairly much duplication of code with just small changes. sql/sql_partition.h: New function headers sql/sql_show.cc: Changed list of values for LIST partitioned tables Also fixed printing of unsigned values in INFORMATION SCHEMA for partitioned table sql/sql_table.cc: Fixed for new interface sql/sql_yacc.yy: Moved definition of struct to partition_element.h Added code to keep track of sign of constants in RANGE and LIST partitions sql/table.cc: Fixed for new interface --- sql/ha_partition.cc | 17 +- sql/partition_element.h | 22 ++- sql/partition_info.cc | 115 ++++++++---- sql/partition_info.h | 23 +-- sql/share/errmsg.txt | 3 + sql/sql_partition.cc | 455 ++++++++++++++++++++++++++++++++++-------------- sql/sql_partition.h | 7 +- sql/sql_show.cc | 9 +- sql/sql_table.cc | 4 +- sql/sql_yacc.yy | 23 ++- sql/table.cc | 3 +- 11 files changed, 478 insertions(+), 203 deletions(-) (limited to 'sql') diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 7cf841a5d71..c9f4c6b02e9 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5165,9 +5165,20 @@ void ha_partition::print_error(int error, myf errflag) if (error == HA_ERR_NO_PARTITION_FOUND) { 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)); + longlong value= m_part_info->part_expr->val_int(); + if (!m_part_info->part_expr->unsigned_flag || + 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)); + } + else + { + ulonglong value= m_part_info->part_expr->val_int(); + longlong2str(value, buf, 10); + my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf); + } } else m_file[0]->print_error(error, errflag); diff --git a/sql/partition_element.h b/sql/partition_element.h index d20715d2408..7063e514901 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -36,15 +36,22 @@ enum partition_state { PART_IS_ADDED= 8 }; +typedef struct p_elem_val +{ + longlong value; + bool null_value; + bool unsigned_flag; +} part_elem_value; + class partition_element :public Sql_alloc { public: List subpartitions; - List list_val_list; + List list_val_list; ulonglong part_max_rows; ulonglong part_min_rows; + longlong range_value; char *partition_name; char *tablespace_name; - longlong range_value; char* part_comment; char* data_file_name; char* index_file_name; @@ -52,13 +59,16 @@ public: enum partition_state part_state; uint16 nodegroup_id; bool has_null_value; + bool signed_flag; + bool max_value; partition_element() - : part_max_rows(0), part_min_rows(0), partition_name(NULL), - tablespace_name(NULL), range_value(0), part_comment(NULL), + : part_max_rows(0), part_min_rows(0), range_value(0), + partition_name(NULL), tablespace_name(NULL), part_comment(NULL), data_file_name(NULL), index_file_name(NULL), - engine_type(NULL),part_state(PART_NORMAL), - nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE) + engine_type(NULL), part_state(PART_NORMAL), + nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), + signed_flag(FALSE), max_value(FALSE) { subpartitions.empty(); list_val_list.empty(); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ad0aa053ae2..7f2fea252f1 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -445,10 +445,12 @@ bool partition_info::check_range_constants() { partition_element* part_def; longlong current_largest_int= LONGLONG_MIN; + ulonglong current_largest_uint= 0; longlong part_range_value_int; uint i; List_iterator it(partitions); bool result= TRUE; + bool signed_flag= !part_expr->unsigned_flag; DBUG_ENTER("partition_info::check_range_constants"); DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts)); @@ -463,19 +465,40 @@ bool partition_info::check_range_constants() do { part_def= it++; - if ((i != (no_parts - 1)) || !defined_max_value) - part_range_value_int= part_def->range_value; - else - part_range_value_int= LONGLONG_MAX; - if (likely(current_largest_int < part_range_value_int)) + if (signed_flag) { - current_largest_int= part_range_value_int; - range_int_array[i]= part_range_value_int; + if ((i != (no_parts - 1)) || !defined_max_value) + part_range_value_int= part_def->range_value; + else + part_range_value_int= LONGLONG_MAX; + if (likely(current_largest_int < part_range_value_int)) + { + current_largest_int= part_range_value_int; + range_int_array[i]= part_range_value_int; + } + else + { + my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); + goto end; + } } else { - my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); - goto end; + 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 (likely(current_largest_uint < upart_range_value_int)) + { + current_largest_uint= upart_range_value_int; + range_int_array[i]= part_range_value_int; + } + else + { + my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); + goto end; + } } } while (++i < no_parts); result= FALSE; @@ -485,8 +508,8 @@ end: /* - A support routine for check_list_constants used by qsort to sort the - constant list expressions. + Support routines for check_list_constants used by qsort to sort the + constant list expressions. One routine for unsigned and one for signed. SYNOPSIS list_part_cmp() @@ -511,6 +534,18 @@ int partition_info::list_part_cmp(const void* a, const void* b) return 0; } +int partition_info::list_part_cmp_unsigned(const void* a, const void* b) +{ + ulonglong a1= ((LIST_PART_ENTRY*)a)->list_value; + ulonglong b1= ((LIST_PART_ENTRY*)b)->list_value; + if (a1 < b1) + return -1; + else if (a1 > b1) + return +1; + else + return 0; +} + /* This routine allocates an array for all list constants to achieve a fast @@ -536,7 +571,7 @@ bool partition_info::check_list_constants() { uint i; uint list_index= 0; - longlong *list_value; + part_elem_value *list_value; bool not_first; bool result= TRUE; longlong curr_value, prev_value; @@ -577,7 +612,7 @@ bool partition_info::check_list_constants() has_null_part_id= i; found_null= TRUE; } - List_iterator list_val_it1(part_def->list_val_list); + List_iterator list_val_it1(part_def->list_val_list); while (list_val_it1++) no_list_values++; } while (++i < no_parts); @@ -593,33 +628,40 @@ bool partition_info::check_list_constants() do { part_def= list_func_it++; - List_iterator list_val_it2(part_def->list_val_list); + List_iterator list_val_it2(part_def->list_val_list); while ((list_value= list_val_it2++)) { - list_array[list_index].list_value= *list_value; + list_array[list_index].list_value= list_value->value; list_array[list_index++].partition_id= i; } } while (++i < no_parts); - qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), - &list_part_cmp); - - not_first= FALSE; - i= prev_value= 0; //prev_value initialised to quiet compiler - do + if (fixed) { - curr_value= list_array[i].list_value; - if (likely(!not_first || prev_value != curr_value)) - { - prev_value= curr_value; - not_first= TRUE; - } + if (!part_expr->unsigned_flag) + qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), + &list_part_cmp); else + 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 { - my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); - goto end; - } - } while (++i < no_list_values); + curr_value= list_array[i].list_value; + if (likely(!not_first || prev_value != curr_value)) + { + prev_value= curr_value; + not_first= TRUE; + } + else + { + my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); + goto end; + } + } while (++i < no_list_values); + } result= FALSE; end: DBUG_RETURN(result); @@ -647,7 +689,7 @@ end: */ -bool partition_info::check_partition_info(handlerton **eng_type, +bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, handler *file, ulonglong max_rows) { handlerton **engine_array= NULL; @@ -733,9 +775,12 @@ bool partition_info::check_partition_info(handlerton **eng_type, list constants. */ - if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) || - (part_type == LIST_PARTITION && check_list_constants()))) - goto end; + if (fixed) + { + if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) || + (part_type == LIST_PARTITION && check_list_constants()))) + goto end; + } result= FALSE; end: my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR)); diff --git a/sql/partition_info.h b/sql/partition_info.h index 664c8834b0b..5a2cacd3c71 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -163,6 +163,7 @@ public: uint no_subpart_fields; uint no_full_part_fields; + uint has_null_part_id; /* This variable is used to calculate the partition id when using LINEAR KEY/HASH. This functionality is kept in the MySQL Server @@ -182,7 +183,6 @@ public: bool fixed; bool from_openfrm; bool has_null_value; - uint has_null_part_id; partition_info() @@ -204,19 +204,13 @@ public: no_parts(0), no_subparts(0), count_curr_subparts(0), part_error_code(0), no_list_values(0), no_part_fields(0), no_subpart_fields(0), - no_full_part_fields(0), linear_hash_mask(0), - use_default_partitions(TRUE), - use_default_no_partitions(TRUE), - use_default_subpartitions(TRUE), - use_default_no_subpartitions(TRUE), - default_partitions_setup(FALSE), - defined_max_value(FALSE), + no_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0), + use_default_partitions(TRUE), use_default_no_partitions(TRUE), + use_default_subpartitions(TRUE), use_default_no_subpartitions(TRUE), + default_partitions_setup(FALSE), defined_max_value(FALSE), list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), - linear_hash_ind(FALSE), - fixed(FALSE), - from_openfrm(FALSE), - has_null_value(FALSE), - has_null_part_id(0) + linear_hash_ind(FALSE), fixed(FALSE), from_openfrm(FALSE), + has_null_value(FALSE) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); @@ -248,10 +242,11 @@ public: static bool check_engine_mix(handlerton **engine_array, uint no_parts); bool check_range_constants(); bool check_list_constants(); - bool check_partition_info(handlerton **eng_type, + bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, ulonglong max_rows); private: static int list_part_cmp(const void* a, const void* b); + static int list_part_cmp_unsigned(const void* a, const void* b); bool set_up_default_partitions(handler *file, ulonglong max_rows, uint start_no); bool set_up_default_subpartitions(handler *file, ulonglong max_rows); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e8766b3d882..3724ff464f2 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5826,3 +5826,6 @@ 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" diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5cae38f2773..4605a4dc28c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -61,7 +61,6 @@ static const char *equal_str= "="; static const char *end_paren_str= ")"; static const char *begin_paren_str= "("; static const char *comma_str= ","; -static char buff[22]; int get_partition_id_list(partition_info *part_info, uint32 *part_id, @@ -189,9 +188,9 @@ bool is_name_in_list(char *name, SYNOPSIS partition_default_handling() table Table object - table_name Table name to use when getting no_parts - db_name Database name to use when getting no_parts part_info Partition info to set up + is_create_table_ind Is this part of a table creation + normalized_path Normalized path name of table and database RETURN VALUES TRUE Error @@ -793,6 +792,43 @@ end: } +/* + Support function to check if all VALUES * (expression) is of the + right sign (no signed constants when unsigned partition function) + + SYNOPSIS + check_signed_flag() + part_info Partition info object + + RETURN VALUES + 0 No errors due to sign errors + >0 Sign error +*/ + +int check_signed_flag(partition_info *part_info) +{ + int error= 0; + uint i= 0; + if (part_info->part_type != HASH_PARTITION && + part_info->part_expr->unsigned_flag) + { + List_iterator part_it(part_info->partitions); + do + { + partition_element *part_elem= part_it++; + + if (part_elem->signed_flag) + { + my_error(ER_SIGNED_PARTITION_CONSTANT_ERROR, MYF(0)); + error= ER_SIGNED_PARTITION_CONSTANT_ERROR; + break; + } + } while (++i < part_info->no_parts); + } + return error; +} + + /* The function uses a new feature in fix_fields where the flag GET_FIXED_FIELDS_FLAG is set for all fields in the item tree. @@ -802,10 +838,11 @@ end: SYNOPSIS fix_fields_part_func() thd The thread object - tables A list of one table, the partitioned table 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 RETURN VALUE TRUE An error occurred, something was wrong with the @@ -828,26 +865,54 @@ end: on the field object. */ -static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, - Item* func_expr, partition_info *part_info, - bool is_sub_part) +bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, + bool is_sub_part, bool is_field_to_be_setup) { + partition_info *part_info= table->part_info; + uint dir_length, home_dir_length; bool result= TRUE; - TABLE *table= tables->table; + TABLE_LIST tables; TABLE_LIST *save_table_list, *save_first_table, *save_last_table; int error; Name_resolution_context *context; const char *save_where; + char* db_name; + char db_name_string[FN_REFLEN]; DBUG_ENTER("fix_fields_part_func"); + if (part_info->fixed) + { + if (!(is_sub_part || (error= check_signed_flag(part_info)))) + result= FALSE; + goto end; + } + + /* + Set-up the TABLE_LIST object to be a list with a single table + Set the object to zero to create NULL pointers and set alias + and real name to table name and get database name from file name. + */ + + bzero((void*)&tables, sizeof(TABLE_LIST)); + tables.alias= tables.table_name= (char*) table->s->table_name.str; + tables.table= table; + tables.next_local= 0; + tables.next_name_resolution_table= 0; + strmov(db_name_string, table->s->normalized_path.str); + dir_length= dirname_length(db_name_string); + db_name_string[dir_length - 1]= 0; + home_dir_length= dirname_length(db_name_string); + db_name= &db_name_string[home_dir_length]; + tables.db= db_name; + context= thd->lex->current_context(); table->map= 1; //To ensure correct calculation of const item table->get_fields_in_item_tree= TRUE; save_table_list= context->table_list; save_first_table= context->first_name_resolution_table; save_last_table= context->last_name_resolution_table; - context->table_list= tables; - context->first_name_resolution_table= tables; + context->table_list= &tables; + context->first_name_resolution_table= &tables; context->last_name_resolution_table= NULL; func_expr->walk(&Item::change_context_processor, (byte*) context); save_where= thd->where; @@ -859,7 +924,8 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, if (unlikely(error)) { DBUG_PRINT("info", ("Field in partition function not part of table")); - clear_field_flag(table); + if (is_field_to_be_setup) + clear_field_flag(table); goto end; } thd->where= save_where; @@ -869,7 +935,13 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, clear_field_flag(table); goto end; } - result= set_up_field_array(table, is_sub_part); + if ((!is_sub_part) && (error= check_signed_flag(part_info))) + goto end; + result= FALSE; + if (is_field_to_be_setup) + result= set_up_field_array(table, is_sub_part); + if (!is_sub_part) + part_info->fixed= TRUE; end: table->get_fields_in_item_tree= FALSE; table->map= 0; //Restore old value @@ -1303,7 +1375,6 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, SYNOPSIS fix_partition_func() thd The thread object - name The name of the partitioned table table TABLE object for which partition fields are set-up create_table_ind Indicator of whether openfrm was called as part of CREATE or ALTER TABLE @@ -1325,15 +1396,10 @@ NOTES of an error that is not discovered until here. */ -bool fix_partition_func(THD *thd, const char* name, TABLE *table, +bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) { bool result= TRUE; - uint dir_length, home_dir_length; - TABLE_LIST tables; - TABLE_SHARE *share= table->s; - char db_name_string[FN_REFLEN]; - char* db_name; partition_info *part_info= table->part_info; ulong save_set_query_id= thd->set_query_id; Item *thd_free_list= thd->free_list; @@ -1345,23 +1411,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, } thd->set_query_id= 0; DBUG_PRINT("info", ("thd->set_query_id: %d", thd->set_query_id)); - /* - Set-up the TABLE_LIST object to be a list with a single table - Set the object to zero to create NULL pointers and set alias - and real name to table name and get database name from file name. - */ - - bzero((void*)&tables, sizeof(TABLE_LIST)); - tables.alias= tables.table_name= (char*) share->table_name.str; - tables.table= table; - tables.next_local= 0; - tables.next_name_resolution_table= 0; - strmov(db_name_string, name); - dir_length= dirname_length(db_name_string); - db_name_string[dir_length - 1]= 0; - home_dir_length= dirname_length(db_name_string); - db_name= &db_name_string[home_dir_length]; - tables.db= db_name; if (!is_create_table_ind || thd->lex->sql_command != SQLCOM_CREATE_TABLE) @@ -1391,9 +1440,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, } else { - if (unlikely(fix_fields_part_func(thd, &tables, - part_info->subpart_expr, part_info, - TRUE))) + if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr, + table, TRUE, TRUE))) goto end; if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT)) { @@ -1420,8 +1468,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, } else { - if (unlikely(fix_fields_part_func(thd, &tables, part_info->part_expr, - part_info, FALSE))) + if (unlikely(fix_fields_part_func(thd, part_info->part_expr, + table, FALSE, TRUE))) goto end; if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) { @@ -1434,6 +1482,9 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, else { const char *error_str; + if (unlikely(fix_fields_part_func(thd, part_info->part_expr, + table, FALSE, TRUE))) + goto end; if (part_info->part_type == RANGE_PARTITION) { error_str= partition_keywords[PKW_RANGE].str; @@ -1457,9 +1508,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str); goto end; } - if (unlikely(fix_fields_part_func(thd, &tables, part_info->part_expr, - part_info, FALSE))) - goto end; if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) { my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str); @@ -1479,7 +1527,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, check_range_capable_PF(table); set_up_partition_key_maps(table, part_info); set_up_partition_func_pointers(part_info); - part_info->fixed= TRUE; set_up_range_analysis_info(part_info); result= FALSE; end: @@ -1563,6 +1610,7 @@ static int add_hash(File fptr) static int add_partition(File fptr) { + char buff[22]; strxmov(buff, part_str, space_str, NullS); return add_string(fptr, buff); } @@ -1576,6 +1624,7 @@ static int add_subpartition(File fptr) static int add_partition_by(File fptr) { + char buff[22]; strxmov(buff, part_str, space_str, by_str, space_str, NullS); return add_string(fptr, buff); } @@ -1616,10 +1665,18 @@ static int add_key_partition(File fptr, List field_list) static int add_int(File fptr, longlong number) { + char buff[32]; llstr(number, buff); return add_string(fptr, buff); } +static int add_uint(File fptr, ulonglong number) +{ + char buff[32]; + longlong2str(number, buff, 10); + return add_string(fptr, buff); +} + static int add_keyword_string(File fptr, const char *keyword, bool should_use_quotes, const char *keystr) @@ -1681,28 +1738,43 @@ static int add_partition_options(File fptr, partition_element *p_elem) } static int add_partition_values(File fptr, partition_info *part_info, - partition_element *p_elem) + partition_element *p_elem) { int err= 0; if (part_info->part_type == RANGE_PARTITION) { err+= add_string(fptr, "VALUES LESS THAN "); - if (p_elem->range_value != LONGLONG_MAX) + if (p_elem->signed_flag) { - err+= add_begin_parenthesis(fptr); - err+= add_int(fptr, p_elem->range_value); - err+= add_end_parenthesis(fptr); + if (!p_elem->max_value) + { + err+= add_begin_parenthesis(fptr); + err+= add_int(fptr, p_elem->range_value); + err+= add_end_parenthesis(fptr); + } + else + err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str); } else - err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str); + { + 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); + } } else if (part_info->part_type == LIST_PARTITION) { uint i; - List_iterator list_val_it(p_elem->list_val_list); + List_iterator list_val_it(p_elem->list_val_list); 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) { @@ -1717,8 +1789,12 @@ static int add_partition_values(File fptr, partition_info *part_info, i= 0; do { - longlong *list_value= list_val_it++; - err+= add_int(fptr, *list_value); + part_elem_value *list_value= list_val_it++; + + if (!list_value->unsigned_flag) + err+= add_int(fptr, list_value->value); + else + err+= add_uint(fptr, list_value->value); if (i != (no_items-1)) err+= add_comma(fptr); } while (++i < no_items); @@ -2294,15 +2370,15 @@ static uint32 get_part_id_linear_key(partition_info *part_info, int get_partition_id_list(partition_info *part_info, - uint32 *part_id, - longlong *func_value) + uint32 *part_id, + longlong *func_value) { LIST_PART_ENTRY *list_array= part_info->list_array; int list_index; - longlong list_value; int min_list_index= 0; int max_list_index= part_info->no_list_values - 1; longlong part_func_value= part_val_int(part_info->part_expr); + bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_list"); if (part_info->part_expr->null_value) @@ -2315,22 +2391,49 @@ int get_partition_id_list(partition_info *part_info, goto notfound; } *func_value= part_func_value; - while (max_list_index >= min_list_index) + if (!unsigned_flag) { - list_index= (max_list_index + min_list_index) >> 1; - list_value= list_array[list_index].list_value; - if (list_value < part_func_value) - min_list_index= list_index + 1; - else if (list_value > part_func_value) + longlong list_value; + while (max_list_index >= min_list_index) { - if (!list_index) - goto notfound; - max_list_index= list_index - 1; + list_index= (max_list_index + min_list_index) >> 1; + list_value= list_array[list_index].list_value; + if (list_value < part_func_value) + min_list_index= list_index + 1; + else if (list_value > part_func_value) + { + if (!list_index) + goto notfound; + max_list_index= list_index - 1; + } + else + { + *part_id= (uint32)list_array[list_index].partition_id; + DBUG_RETURN(0); + } } - else + } + else + { + ulonglong ulist_value; + ulonglong upart_func_value= part_func_value; + while (max_list_index >= min_list_index) { - *part_id= (uint32)list_array[list_index].partition_id; - DBUG_RETURN(0); + list_index= (max_list_index + min_list_index) >> 1; + ulist_value= list_array[list_index].list_value; + if (ulist_value < upart_func_value) + min_list_index= list_index + 1; + else if (ulist_value > upart_func_value) + { + if (!list_index) + goto notfound; + max_list_index= list_index - 1; + } + else + { + *part_id= (uint32)list_array[list_index].partition_id; + DBUG_RETURN(0); + } } } notfound: @@ -2381,34 +2484,65 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint) { - DBUG_ENTER("get_list_array_idx_for_endpoint"); LIST_PART_ENTRY *list_array= part_info->list_array; uint list_index; - longlong list_value; uint min_list_index= 0, max_list_index= part_info->no_list_values - 1; /* Get the partitioning function value for the endpoint */ longlong part_func_value= part_val_int(part_info->part_expr); - while (max_list_index >= min_list_index) + bool unsigned_flag= part_info->part_expr->unsigned_flag; + DBUG_ENTER("get_list_array_idx_for_endpoint"); + + if (!unsigned_flag) { - list_index= (max_list_index + min_list_index) >> 1; - list_value= list_array[list_index].list_value; - if (list_value < part_func_value) - min_list_index= list_index + 1; - else if (list_value > part_func_value) + longlong list_value; + while (max_list_index >= min_list_index) { - if (!list_index) - goto notfound; - max_list_index= list_index - 1; + list_index= (max_list_index + min_list_index) >> 1; + list_value= list_array[list_index].list_value; + if (list_value < part_func_value) + min_list_index= list_index + 1; + else if (list_value > part_func_value) + { + if (!list_index) + goto notfound_signed; + max_list_index= list_index - 1; + } + else + { + DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); + } } - else + notfound_signed: + if (list_value < part_func_value) + list_index++; + DBUG_RETURN(list_index); + } + else + { + ulonglong upart_func_value= part_func_value; + ulonglong ulist_value; + while (max_list_index >= min_list_index) { - DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); + list_index= (max_list_index + min_list_index) >> 1; + ulist_value= list_array[list_index].list_value; + if (ulist_value < upart_func_value) + min_list_index= list_index + 1; + else if (ulist_value > upart_func_value) + { + if (!list_index) + goto notfound_unsigned; + max_list_index= list_index - 1; + } + else + { + DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); + } } + notfound_unsigned: + if (ulist_value < upart_func_value) + list_index++; + DBUG_RETURN(list_index); } -notfound: - if (list_value < part_func_value) - list_index++; - DBUG_RETURN(list_index); } @@ -2422,6 +2556,7 @@ int get_partition_id_range(partition_info *part_info, uint max_part_id= max_partition; uint loc_part_id; longlong part_func_value= part_val_int(part_info->part_expr); + bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_int_range"); if (part_info->part_expr->null_value) @@ -2429,24 +2564,52 @@ int get_partition_id_range(partition_info *part_info, *part_id= 0; DBUG_RETURN(0); } - while (max_part_id > min_part_id) + *func_value= part_func_value; + if (!unsigned_flag) { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - if (range_array[loc_part_id] <= part_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; + while (max_part_id > min_part_id) + { + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + if (range_array[loc_part_id] <= part_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; + } + loc_part_id= max_part_id; + if (part_func_value >= range_array[loc_part_id]) + if (loc_part_id != max_partition) + loc_part_id++; + *part_id= (uint32)loc_part_id; + if (loc_part_id == max_partition) + if (range_array[loc_part_id] != LONGLONG_MAX) + if (part_func_value >= range_array[loc_part_id]) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + } + else + { + ulonglong upart_func_value= part_func_value; + ulonglong urange_value; + while (max_part_id > min_part_id) + { + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + urange_value= range_array[loc_part_id]; + if (urange_value <= upart_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; + } + loc_part_id= max_part_id; + urange_value= range_array[loc_part_id]; + if (upart_func_value >= urange_value) + if (loc_part_id != max_partition) + loc_part_id++; + *part_id= (uint32)loc_part_id; + urange_value= range_array[loc_part_id]; + if (loc_part_id == max_partition) + if (urange_value != ULONGLONG_MAX) + if (upart_func_value >= urange_value) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); } - loc_part_id= max_part_id; - if (part_func_value >= range_array[loc_part_id]) - if (loc_part_id != max_partition) - loc_part_id++; - *part_id= (uint32)loc_part_id; - *func_value= part_func_value; - if (loc_part_id == max_partition) - if (range_array[loc_part_id] != LONGLONG_MAX) - if (part_func_value >= range_array[loc_part_id]) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); DBUG_RETURN(0); } @@ -2496,39 +2659,79 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint) { - DBUG_ENTER("get_partition_id_range_for_endpoint"); longlong *range_array= part_info->range_int_array; uint max_partition= part_info->no_parts - 1; 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); + bool unsigned_flag= part_info->part_expr->unsigned_flag; + DBUG_ENTER("get_partition_id_range_for_endpoint"); - while (max_part_id > min_part_id) + if (!unsigned_flag) { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - if (range_array[loc_part_id] <= part_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; - } - loc_part_id= max_part_id; - if (loc_part_id < max_partition && - part_func_value >= range_array[loc_part_id+1]) - { - loc_part_id++; - } - if (left_endpoint) - { - if (part_func_value >= range_array[loc_part_id]) + while (max_part_id > min_part_id) + { + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + if (range_array[loc_part_id] <= part_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; + } + loc_part_id= max_part_id; + if (loc_part_id < max_partition && + part_func_value >= range_array[loc_part_id+1]) + { + loc_part_id++; + } + if (left_endpoint) + { + if (part_func_value >= range_array[loc_part_id]) + loc_part_id++; + } + else + { + if (part_func_value == range_array[loc_part_id]) + loc_part_id += test(include_endpoint); + else if (part_func_value > range_array[loc_part_id]) + loc_part_id++; loc_part_id++; + } } - else + else { - if (part_func_value == range_array[loc_part_id]) - loc_part_id += test(include_endpoint); - else if (part_func_value > range_array[loc_part_id]) + ulonglong upart_func_value= part_func_value; + ulonglong urange_value; + while (max_part_id > min_part_id) + { + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + urange_value= range_array[loc_part_id]; + if (urange_value <= upart_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; + } + loc_part_id= max_part_id; + urange_value= range_array[loc_part_id+1]; + if (loc_part_id < max_partition && + upart_func_value >= urange_value) + { + loc_part_id++; + } + if (left_endpoint) + { + urange_value= range_array[loc_part_id]; + if (upart_func_value >= urange_value) + loc_part_id++; + } + else + { + urange_value= range_array[loc_part_id]; + if (upart_func_value == urange_value) + loc_part_id += test(include_endpoint); + else if (upart_func_value > urange_value) + loc_part_id++; loc_part_id++; - loc_part_id++; + } } DBUG_RETURN(loc_part_id); } @@ -4497,8 +4700,8 @@ the generated partition syntax in a correct manner. tab_part_info->use_default_subpartitions= FALSE; tab_part_info->use_default_no_subpartitions= FALSE; } - if (tab_part_info->check_partition_info((handlerton**)NULL, - table->file, ULL(0))) + if (tab_part_info->check_partition_info(thd, (handlerton**)NULL, + table->file, ULL(0))) { DBUG_RETURN(TRUE); } diff --git a/sql/sql_partition.h b/sql/sql_partition.h index fd2c474236f..9fde3db2883 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -65,9 +65,8 @@ int get_part_for_delete(const byte *buf, const byte *rec0, partition_info *part_info, uint32 *part_id); void prune_partition_set(const TABLE *table, part_id_range *part_spec); bool check_partition_info(partition_info *part_info,handlerton **eng_type, - handler *file, ulonglong max_rows); -bool fix_partition_func(THD *thd, const char *name, TABLE *table, - bool create_table_ind); + TABLE *table, handler *file, ulonglong max_rows); +bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind); char *generate_partition_syntax(partition_info *part_info, uint *buf_length, bool use_sql_alloc, bool write_all); @@ -91,6 +90,8 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); +bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, + bool is_sub_part, bool is_field_to_be_setup); /* A "Get next" function for partition iterator. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 19535f3182a..86515355936 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3851,8 +3851,8 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, } else if (part_info->part_type == LIST_PARTITION) { - List_iterator list_val_it(part_elem->list_val_list); - longlong *list_value; + List_iterator list_val_it(part_elem->list_val_list); + part_elem_value *list_value; uint no_items= part_elem->list_val_list.elements; tmp_str.length(0); tmp_res.length(0); @@ -3864,7 +3864,10 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, } while ((list_value= list_val_it++)) { - tmp_res.set(*list_value, cs); + if (!list_value->unsigned_flag) + tmp_res.set(list_value->value, cs); + else + tmp_res.set((ulonglong)list_value->value, cs); tmp_str.append(tmp_res); if (--no_items != 0) tmp_str.append(","); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2687b64841f..71ffb4d28b7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2141,8 +2141,8 @@ bool mysql_create_table_internal(THD *thd, } DBUG_PRINT("info", ("db_type = %d", ha_legacy_type(part_info->default_engine_type))); - if (part_info->check_partition_info( &engine_type, file, - create_info->max_rows)) + if (part_info->check_partition_info(thd, &engine_type, file, + create_info->max_rows)) goto err; part_info->default_engine_type= engine_type; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e48748bcfa5..8037eaa5b21 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -42,12 +42,6 @@ #include #include -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}; @@ -3712,6 +3706,7 @@ part_func_max: YYABORT; } lex->part_info->defined_max_value= TRUE; + lex->part_info->curr_part_elem->max_value= TRUE; lex->part_info->curr_part_elem->range_value= LONGLONG_MAX; } | part_range_func @@ -3727,7 +3722,10 @@ part_func_max: part_range_func: '(' part_bit_expr ')' { - Lex->part_info->curr_part_elem->range_value= $2->value; + partition_info *part_info= Lex->part_info; + if (!($2->unsigned_flag)) + part_info->curr_part_elem->signed_flag= TRUE; + part_info->curr_part_elem->range_value= $2->value; } ; @@ -3740,9 +3738,12 @@ part_list_item: part_bit_expr { part_elem_value *value_ptr= $1; + partition_info *part_info= Lex->part_info; + if (!value_ptr->unsigned_flag) + part_info->curr_part_elem->signed_flag= TRUE; if (!value_ptr->null_value && - Lex->part_info->curr_part_elem-> - list_val_list.push_back((longlong*) &value_ptr->value)) + part_info->curr_part_elem-> + list_val_list.push_back(value_ptr)) { mem_alloc_error(sizeof(part_elem_value)); YYABORT; @@ -3783,6 +3784,10 @@ part_bit_expr: } thd->where= save_where; value_ptr->value= part_expr->val_int(); + value_ptr->unsigned_flag= TRUE; + if (!part_expr->unsigned_flag && + value_ptr->value < 0) + value_ptr->unsigned_flag= FALSE; if ((value_ptr->null_value= part_expr->null_value)) { if (Lex->part_info->curr_part_elem->has_null_value) diff --git a/sql/table.cc b/sql/table.cc index 41621a19900..7252940eb27 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1488,8 +1488,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, Fix the partition functions and ensure they are not constant functions */ - if (fix_partition_func(thd, share->normalized_path.str, outparam, - is_create_table)) + if (fix_partition_func(thd, outparam, is_create_table)) goto err; } #endif -- cgit v1.2.1 From 10c5b8b6fd63365d5d3812964912752a6a89510b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 May 2006 00:08:48 -0400 Subject: BUG#19801: Valgrind error in check_list_constants Needed some special handling of the case when no_list_values == 0 mysql-test/r/partition.result: Added a couple of new test cases mysql-test/t/partition.test: Added a couple of new test cases sql/partition_info.cc: Rearranged some code to handle case where no_list_values == 0 which happens when one partition with only one value == NULL. sql/sql_partition.cc: Rearranged code to remove compiler warning and also since we now have handled the case where no_list_values == 0 in a special case before coming here Added code for handling the special case where no_list_values == 0 --- sql/partition_info.cc | 41 +++++++++++++++++++++++------------------ sql/sql_partition.cc | 21 +++++++++++++++++---- 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'sql') diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 0924a8adf6e..6e3023289d8 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -612,7 +612,8 @@ bool partition_info::check_list_constants() no_list_values++; } while (++i < no_parts); list_func_it.rewind(); - list_array= (LIST_PART_ENTRY*)sql_alloc(no_list_values*sizeof(LIST_PART_ENTRY)); + list_array= (LIST_PART_ENTRY*)sql_alloc((no_list_values+1) * + sizeof(LIST_PART_ENTRY)); if (unlikely(list_array == NULL)) { mem_alloc_error(no_list_values * sizeof(LIST_PART_ENTRY)); @@ -631,25 +632,29 @@ bool partition_info::check_list_constants() } } while (++i < no_parts); - qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), - &list_part_cmp); - - not_first= FALSE; - i= prev_value= 0; //prev_value initialised to quiet compiler - do + if (no_list_values) { - curr_value= list_array[i].list_value; - if (likely(!not_first || prev_value != curr_value)) - { - prev_value= curr_value; - not_first= TRUE; - } - else + qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), + &list_part_cmp); + + not_first= FALSE; + i= prev_value= 0; //prev_value initialised to quiet compiler + do { - my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); - goto end; - } - } while (++i < no_list_values); + DBUG_ASSERT(i < no_list_values); + curr_value= list_array[i].list_value; + if (likely(!not_first || prev_value != curr_value)) + { + prev_value= curr_value; + not_first= TRUE; + } + else + { + my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); + goto end; + } + } while (++i < no_list_values); + } result= FALSE; end: DBUG_RETURN(result); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index e946e972968..b6756821245 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2257,8 +2257,8 @@ static uint32 get_part_id_linear_key(partition_info *part_info, int get_partition_id_list(partition_info *part_info, - uint32 *part_id, - longlong *func_value) + uint32 *part_id, + longlong *func_value) { LIST_PART_ENTRY *list_array= part_info->list_array; int list_index; @@ -2351,7 +2351,8 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint min_list_index= 0, max_list_index= part_info->no_list_values - 1; /* Get the partitioning function value for the endpoint */ longlong part_func_value= part_val_int(part_info->part_expr); - while (max_list_index >= min_list_index) + DBUG_ASSERT(part_info->no_list_values); + do { list_index= (max_list_index + min_list_index) >> 1; list_value= list_array[list_index].list_value; @@ -2367,7 +2368,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, { DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); } - } + } while (max_list_index >= min_list_index); notfound: if (list_value < part_func_value) list_index++; @@ -6194,6 +6195,18 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, part_iter->get_next= get_next_partition_id_list; part_iter->part_info= part_info; part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; + if (max_endpoint_val == 0) + { + /* + We handle this special case without optimisations since it is + of little practical value but causes a great number of complex + checks later in the code. + */ + part_iter->part_nums.start= part_iter->part_nums.end= 0; + part_iter->part_nums.cur= 0; + part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE; + return -1; + } } else DBUG_ASSERT(0); -- cgit v1.2.1 From e05d2d06cb4adfe27dc4c0c4cb8f445332e9ab80 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 Jun 2006 14:55:22 -0400 Subject: 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. --- 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 ++++++- 6 files changed, 39 insertions(+), 43 deletions(-) (limited to 'sql') 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); - } - 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_end_parenthesis(fptr); } + else + 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 ')' { -- cgit v1.2.1 From 5239cba4b58071ea1aa16ff823305f0498078e0a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Jun 2006 11:54:21 -0400 Subject: BUG#16002: More review fixes mysql-test/r/partition_range.result: Changed test cases mysql-test/t/partition_range.test: Changed test cases sql/partition_info.cc: Changes to resue signed integer code for unsigned integer partition functions Basic idea is to store value - 0x8000000000000000 in list_array and range_int_array and also perform this subtraction before applying get_partition_id_range and so forth. sql/sql_partition.cc: Changes to resue signed integer code for unsigned integer partition functions Basic idea is to store value - 0x8000000000000000 in list_array and range_int_array and also perform this subtraction before applying get_partition_id_range and so forth. --- sql/partition_info.cc | 76 ++++++--------- sql/sql_partition.cc | 265 ++++++++++++++------------------------------------ 2 files changed, 106 insertions(+), 235 deletions(-) (limited to 'sql') diff --git a/sql/partition_info.cc b/sql/partition_info.cc index a6ca1e0107e..a7ab59adb81 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -444,9 +444,9 @@ bool partition_info::check_engine_mix(handlerton **engine_array, uint no_parts) bool partition_info::check_range_constants() { partition_element* part_def; - longlong current_largest_int= LONGLONG_MIN; - ulonglong current_largest_uint= 0; - longlong part_range_value_int; + longlong current_largest; + longlong part_range_value; + bool first= TRUE; uint i; List_iterator it(partitions); bool result= TRUE; @@ -465,33 +465,26 @@ bool partition_info::check_range_constants() do { part_def= it++; - if (signed_flag) + if ((i != (no_parts - 1)) || !defined_max_value) { - if ((i != (no_parts - 1)) || !defined_max_value) - part_range_value_int= part_def->range_value; - else - part_range_value_int= LONGLONG_MAX; - if (likely(current_largest_int < part_range_value_int)) - { - current_largest_int= part_range_value_int; - range_int_array[i]= part_range_value_int; - } - else - { - my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); - goto end; - } + part_range_value= part_def->range_value; + if (!signed_flag) + part_range_value-= 0x8000000000000000ULL; + } + else + part_range_value= LONGLONG_MAX; + if (first) + { + current_largest= part_range_value; + range_int_array[0]= part_range_value; + first= FALSE; } else { - ulonglong upart_range_value_int; - 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)) + if (likely(current_largest < part_range_value)) { - current_largest_uint= upart_range_value_int; - range_int_array[i]= part_range_value_int; + current_largest= part_range_value; + range_int_array[i]= part_range_value; } else { @@ -533,18 +526,6 @@ int partition_info::list_part_cmp(const void* a, const void* b) return 0; } -int partition_info::list_part_cmp_unsigned(const void* a, const void* b) -{ - ulonglong a1= ((LIST_PART_ENTRY*)a)->list_value; - ulonglong b1= ((LIST_PART_ENTRY*)b)->list_value; - if (a1 < b1) - return -1; - else if (a1 > b1) - return +1; - else - return 0; -} - /* This routine allocates an array for all list constants to achieve a fast @@ -572,7 +553,7 @@ bool partition_info::check_list_constants() uint list_index= 0; part_elem_value *list_value; bool result= TRUE; - longlong curr_value, prev_value; + longlong curr_value, prev_value, type_add, calc_value; partition_element* part_def; bool found_null= FALSE; List_iterator list_func_it(partitions); @@ -623,13 +604,22 @@ bool partition_info::check_list_constants() } i= 0; + /* + Fix to be able to reuse signed sort functions also for unsigned + partition functions. + */ + type_add= (longlong)(part_expr->unsigned_flag ? + 0x8000000000000000ULL : + 0ULL); + do { part_def= list_func_it++; List_iterator list_val_it2(part_def->list_val_list); while ((list_value= list_val_it2++)) { - list_array[list_index].list_value= list_value->value; + calc_value= list_value->value - type_add; + list_array[list_index].list_value= calc_value; list_array[list_index++].partition_id= i; } } while (++i < no_parts); @@ -637,12 +627,8 @@ 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); - else - qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), - &list_part_cmp_unsigned); + qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), + &list_part_cmp); i= prev_value= 0; //prev_value initialised to quiet compiler do diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 45cd13ce854..086b7f28b1e 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1752,8 +1752,7 @@ static int add_partition_options(File fptr, partition_element *p_elem) return err + add_engine(fptr,p_elem->engine_type); } -static int add_partition_values(File fptr, partition_info *part_info, - partition_element *p_elem) +static int add_partition_values(File fptr, partition_info *part_info, partition_element *p_elem) { int err= 0; @@ -1766,7 +1765,7 @@ static int add_partition_values(File fptr, partition_info *part_info, if (p_elem->signed_flag) err+= add_int(fptr, p_elem->range_value); else - err+= add_uint(fptr, (ulonglong)p_elem->range_value); + err+= add_uint(fptr, p_elem->range_value); err+= add_end_parenthesis(fptr); } else @@ -2382,6 +2381,7 @@ int get_partition_id_list(partition_info *part_info, int min_list_index= 0; int max_list_index= part_info->no_list_values - 1; longlong part_func_value= part_val_int(part_info->part_expr); + longlong list_value; bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_list"); @@ -2394,50 +2394,25 @@ int get_partition_id_list(partition_info *part_info, } goto notfound; } + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; *func_value= part_func_value; - if (!unsigned_flag) + while (max_list_index >= min_list_index) { - longlong list_value; - while (max_list_index >= min_list_index) + list_index= (max_list_index + min_list_index) >> 1; + list_value= list_array[list_index].list_value; + if (list_value < part_func_value) + min_list_index= list_index + 1; + else if (list_value > part_func_value) { - list_index= (max_list_index + min_list_index) >> 1; - list_value= list_array[list_index].list_value; - if (list_value < part_func_value) - min_list_index= list_index + 1; - else if (list_value > part_func_value) - { - if (!list_index) - goto notfound; - max_list_index= list_index - 1; - } - else - { - *part_id= (uint32)list_array[list_index].partition_id; - DBUG_RETURN(0); - } + if (!list_index) + goto notfound; + max_list_index= list_index - 1; } - } - else - { - ulonglong ulist_value; - ulonglong upart_func_value= part_func_value; - while (max_list_index >= min_list_index) + else { - list_index= (max_list_index + min_list_index) >> 1; - ulist_value= list_array[list_index].list_value; - if (ulist_value < upart_func_value) - min_list_index= list_index + 1; - else if (ulist_value > upart_func_value) - { - if (!list_index) - goto notfound; - max_list_index= list_index - 1; - } - else - { - *part_id= (uint32)list_array[list_index].partition_id; - DBUG_RETURN(0); - } + *part_id= (uint32)list_array[list_index].partition_id; + DBUG_RETURN(0); } } notfound: @@ -2496,57 +2471,30 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_list_array_idx_for_endpoint"); - if (!unsigned_flag) + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; + longlong list_value; + while (max_list_index >= min_list_index) { - longlong list_value; - while (max_list_index >= min_list_index) + list_index= (max_list_index + min_list_index) >> 1; + list_value= list_array[list_index].list_value; + if (list_value < part_func_value) + min_list_index= list_index + 1; + else if (list_value > part_func_value) { - list_index= (max_list_index + min_list_index) >> 1; - list_value= list_array[list_index].list_value; - if (list_value < part_func_value) - min_list_index= list_index + 1; - else if (list_value > part_func_value) - { - if (!list_index) - goto notfound_signed; - max_list_index= list_index - 1; - } - else - { - DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); - } + if (!list_index) + goto notfound; + max_list_index= list_index - 1; } - notfound_signed: - if (list_value < part_func_value) - list_index++; - DBUG_RETURN(list_index); - } - else - { - ulonglong upart_func_value= part_func_value; - ulonglong ulist_value; - while (max_list_index >= min_list_index) + else { - list_index= (max_list_index + min_list_index) >> 1; - ulist_value= list_array[list_index].list_value; - if (ulist_value < upart_func_value) - min_list_index= list_index + 1; - else if (ulist_value > upart_func_value) - { - if (!list_index) - goto notfound_unsigned; - max_list_index= list_index - 1; - } - else - { - DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); - } + DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); } - notfound_unsigned: - if (ulist_value < upart_func_value) - list_index++; - DBUG_RETURN(list_index); } +notfound: + if (list_value < part_func_value) + list_index++; + DBUG_RETURN(list_index); } @@ -2568,52 +2516,26 @@ int get_partition_id_range(partition_info *part_info, *part_id= 0; DBUG_RETURN(0); } + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; *func_value= part_func_value; - if (!unsigned_flag) - { - while (max_part_id > min_part_id) - { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - if (range_array[loc_part_id] <= part_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; - } - loc_part_id= max_part_id; - if (part_func_value >= range_array[loc_part_id]) - if (loc_part_id != max_partition) - loc_part_id++; - *part_id= (uint32)loc_part_id; - if (loc_part_id == max_partition) - if (range_array[loc_part_id] != LONGLONG_MAX) - if (part_func_value >= range_array[loc_part_id]) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); - } - else + while (max_part_id > min_part_id) { - ulonglong upart_func_value= part_func_value; - ulonglong urange_value; - while (max_part_id > min_part_id) - { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - urange_value= range_array[loc_part_id]; - if (urange_value <= upart_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; - } - loc_part_id= max_part_id; - urange_value= range_array[loc_part_id]; - if (upart_func_value >= urange_value) - if (loc_part_id != max_partition) - loc_part_id++; - *part_id= (uint32)loc_part_id; - urange_value= range_array[loc_part_id]; - if (loc_part_id == max_partition) - if (urange_value != ULONGLONG_MAX) - if (upart_func_value >= urange_value) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + if (range_array[loc_part_id] <= part_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; } + loc_part_id= max_part_id; + if (part_func_value >= range_array[loc_part_id]) + if (loc_part_id != max_partition) + loc_part_id++; + *part_id= (uint32)loc_part_id; + if (loc_part_id == max_partition) + if (range_array[loc_part_id] != LONGLONG_MAX) + if (part_func_value >= range_array[loc_part_id]) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); DBUG_RETURN(0); } @@ -2671,71 +2593,34 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_range_for_endpoint"); - if (!unsigned_flag) + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; + 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; - if (range_array[loc_part_id] <= part_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; - } - loc_part_id= max_part_id; - if (loc_part_id < max_partition && - part_func_value >= range_array[loc_part_id+1]) - { - loc_part_id++; - } - if (left_endpoint) - { - if (part_func_value >= range_array[loc_part_id]) - loc_part_id++; - } - else - { - if (part_func_value == range_array[loc_part_id]) - loc_part_id += test(include_endpoint); - else if (part_func_value > range_array[loc_part_id]) - loc_part_id++; + loc_part_id= (max_part_id + min_part_id + 1) >> 1; + if (range_array[loc_part_id] <= part_func_value) + min_part_id= loc_part_id + 1; + else + max_part_id= loc_part_id - 1; + } + loc_part_id= max_part_id; + if (loc_part_id < max_partition && + part_func_value >= range_array[loc_part_id+1]) + { + loc_part_id++; + } + if (left_endpoint) + { + if (part_func_value >= range_array[loc_part_id]) loc_part_id++; - } } - else + else { - ulonglong upart_func_value= part_func_value; - ulonglong urange_value; - while (max_part_id > min_part_id) - { - loc_part_id= (max_part_id + min_part_id + 1) >> 1; - urange_value= range_array[loc_part_id]; - if (urange_value <= upart_func_value) - min_part_id= loc_part_id + 1; - else - max_part_id= loc_part_id - 1; - } - loc_part_id= max_part_id; - urange_value= range_array[loc_part_id+1]; - if (loc_part_id < max_partition && - upart_func_value >= urange_value) - { - loc_part_id++; - } - if (left_endpoint) - { - urange_value= range_array[loc_part_id]; - if (upart_func_value >= urange_value) - loc_part_id++; - } - else - { - urange_value= range_array[loc_part_id]; - if (upart_func_value == urange_value) - loc_part_id += test(include_endpoint); - else if (upart_func_value > urange_value) - loc_part_id++; + if (part_func_value == range_array[loc_part_id]) + loc_part_id += test(include_endpoint); + else if (part_func_value > range_array[loc_part_id]) loc_part_id++; - } + loc_part_id++; } DBUG_RETURN(loc_part_id); } -- cgit v1.2.1 From 7fafb1eaff524266125eb5c54f35f51eda46a677 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Jun 2006 13:19:46 -0400 Subject: BUG#16002: After review fixes Fixes for NDB sql/ha_ndbcluster.cc: Fixes for NDB sql/sql_partition.cc: Fixes for NDB --- sql/ha_ndbcluster.cc | 6 ++++++ sql/sql_partition.cc | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 587eabb82d2..32f41bbb689 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -9499,6 +9499,7 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info) MYF(0)); uint i; int error= 0; + bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("set_range_data"); if (!range_data) @@ -9509,6 +9510,8 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info) for (i= 0; i < part_info->no_parts; i++) { longlong range_val= part_info->range_int_array[i]; + if (unsigned_flag) + range_val-= 0x8000000000000000ULL; if (range_val < INT_MIN32 || range_val >= INT_MAX32) { if ((i != part_info->no_parts - 1) || @@ -9535,6 +9538,7 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info) * sizeof(int32), MYF(0)); uint32 *part_id, i; int error= 0; + bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("set_list_data"); if (!list_data) @@ -9546,6 +9550,8 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info) { LIST_PART_ENTRY *list_entry= &part_info->list_array[i]; longlong list_val= list_entry->list_value; + if (unsigned_flag) + list_val-= 0x8000000000000000ULL; if (list_val < INT_MIN32 || list_val > INT_MAX32) { my_error(ER_LIMITED_PART_RANGE, MYF(0), "NDB"); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 086b7f28b1e..a9f9e59c0cc 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2394,9 +2394,9 @@ int get_partition_id_list(partition_info *part_info, } goto notfound; } + *func_value= part_func_value; if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; - *func_value= part_func_value; while (max_list_index >= min_list_index) { list_index= (max_list_index + min_list_index) >> 1; @@ -2509,16 +2509,16 @@ int get_partition_id_range(partition_info *part_info, uint loc_part_id; longlong part_func_value= part_val_int(part_info->part_expr); bool unsigned_flag= part_info->part_expr->unsigned_flag; - DBUG_ENTER("get_partition_id_int_range"); + DBUG_ENTER("get_partition_id_range"); if (part_info->part_expr->null_value) { *part_id= 0; DBUG_RETURN(0); } + *func_value= part_func_value; if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; - *func_value= part_func_value; while (max_part_id > min_part_id) { loc_part_id= (max_part_id + min_part_id + 1) >> 1; -- cgit v1.2.1 From 6e9bdcc9e91db27ca37535f7d4989d08727d1902 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Jun 2006 08:31:38 -0400 Subject: BUG#16002: Unsigned partition function support After review fix sql/sql_partition.cc: After review fix --- sql/sql_partition.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index a9f9e59c0cc..6b111f8406d 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2532,10 +2532,10 @@ int get_partition_id_range(partition_info *part_info, if (loc_part_id != max_partition) loc_part_id++; *part_id= (uint32)loc_part_id; - if (loc_part_id == max_partition) - if (range_array[loc_part_id] != LONGLONG_MAX) - if (part_func_value >= range_array[loc_part_id]) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + if (loc_part_id == max_partition && + range_array[loc_part_id] != LONGLONG_MAX && + part_func_value >= range_array[loc_part_id]) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); DBUG_RETURN(0); } -- cgit v1.2.1 From a4c2d33ed976de778f1ff526b6d524a3ffe844c9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Jun 2006 08:35:19 -0400 Subject: BUG#19801: Problems with single partition with only NULL allowed in LIST partitioning After review fix sql/partition_info.cc: After review fix --- sql/partition_info.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sql') diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 6e3023289d8..988c24ae344 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -567,7 +567,6 @@ bool partition_info::check_list_constants() uint i; uint list_index= 0; longlong *list_value; - bool not_first; bool result= TRUE; longlong curr_value, prev_value; partition_element* part_def; @@ -634,19 +633,19 @@ bool partition_info::check_list_constants() if (no_list_values) { + bool first= TRUE; qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), &list_part_cmp); - not_first= FALSE; i= prev_value= 0; //prev_value initialised to quiet compiler do { DBUG_ASSERT(i < no_list_values); 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 { -- cgit v1.2.1 From 4414b56d85d937354e2fb384604394ec3d1ffc56 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Jun 2006 19:40:06 -0400 Subject: merge update mysql-test/t/partition.test: merge error --- sql/ha_ndbcluster.cc | 9 +-------- sql/ha_partition.cc | 9 +-------- sql/partition_info.cc | 24 ++++++++++++++++++++++++ sql/partition_info.h | 3 ++- 4 files changed, 28 insertions(+), 17 deletions(-) (limited to 'sql') diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index d1bd4e057ae..caeb0631d85 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6420,14 +6420,7 @@ void ha_ndbcluster::print_error(int error, myf errflag) DBUG_PRINT("enter", ("error = %d", error)); if (error == HA_ERR_NO_PARTITION_FOUND) - { - char buf[100]; - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); - 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)); - dbug_tmp_restore_column_map(table->read_set, old_map); - } + m_part_info->print_no_partition_found(table); else handler::print_error(error, errflag); DBUG_VOID_RETURN; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index f151d89bb1a..93fb6409f9f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5097,14 +5097,7 @@ void ha_partition::print_error(int error, myf errflag) DBUG_PRINT("enter", ("error: %d", error)); if (error == HA_ERR_NO_PARTITION_FOUND) - { - char buf[100]; - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); - 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)); - dbug_tmp_restore_column_map(table->read_set, old_map); - } + m_part_info->print_no_partition_found(table); else m_file[0]->print_error(error, errflag); DBUG_VOID_RETURN; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 51230a0f5c0..39c8d976732 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -827,4 +827,28 @@ end: } +/* + Print error for no partition found + SYNOPSIS + print_no_partition_found() + table Table object + RETURN VALUES + NONE +*/ + +void partition_info::print_no_partition_found(TABLE *table) +{ + char buf[100]; + char *buf_ptr= (char*)&buf; + my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); + + if (part_expr->null_value) + buf_ptr= (char*)"NULL"; + else + longlong2str(part_expr->val_int(), buf, + part_expr->unsigned_flag ? 10 : -10); + my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf_ptr); + dbug_tmp_restore_column_map(table->read_set, old_map); +} + #endif /* WITH_PARTITION_STORAGE_ENGINE */ diff --git a/sql/partition_info.h b/sql/partition_info.h index f195e555934..3d8c6a40221 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -217,7 +217,7 @@ public: list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), linear_hash_ind(FALSE), fixed(FALSE), is_auto_partitioned(FALSE), from_openfrm(FALSE), - has_null_value(FALSE), has_null_part_id(0) + has_null_value(FALSE) { all_fields_in_PF.clear_all(); all_fields_in_PPF.clear_all(); @@ -251,6 +251,7 @@ public: bool check_list_constants(); bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, ulonglong max_rows); + void print_no_partition_found(TABLE *table); private: static int list_part_cmp(const void* a, const void* b); static int list_part_cmp_unsigned(const void* a, const void* b); -- cgit v1.2.1