diff options
Diffstat (limited to 'sql/sql_partition.cc')
-rw-r--r-- | sql/sql_partition.cc | 242 |
1 files changed, 160 insertions, 82 deletions
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index db69fd3daef..44c0b8ffcd9 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 @@ -794,6 +793,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<partition_element> part_it(part_info->partitions); + do + { + partition_element *part_elem= part_it++; + + if (part_elem->signed_flag) + { + my_error(ER_PARTITION_CONST_DOMAIN_ERROR, MYF(0)); + error= ER_PARTITION_CONST_DOMAIN_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. This field must always be reset before returning from the function @@ -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 + 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 @@ -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, 0, (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,9 +1375,8 @@ 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 + is_create_table_ind Indicator of whether openfrm was called as part of CREATE or ALTER TABLE RETURN VALUE @@ -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; enum_mark_columns save_mark_used_columns= thd->mark_used_columns; Item *thd_free_list= thd->free_list; @@ -1345,23 +1411,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, } thd->mark_used_columns= MARK_COLUMNS_NONE; DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); - /* - 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); } @@ -1631,10 +1680,18 @@ static int add_name_string(File fptr, const char *name) 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) @@ -1696,18 +1753,20 @@ 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; if (part_info->part_type == RANGE_PARTITION) { err+= add_string(fptr, " VALUES LESS THAN "); - if (p_elem->range_value != LONGLONG_MAX) + if (!p_elem->max_value) { err+= add_begin_parenthesis(fptr); - err+= add_int(fptr, p_elem->range_value); + if (p_elem->signed_flag) + err+= add_int(fptr, p_elem->range_value); + else + err+= add_uint(fptr, p_elem->range_value); err+= add_end_parenthesis(fptr); } else @@ -1716,9 +1775,10 @@ static int add_partition_values(File fptr, partition_info *part_info, else if (part_info->part_type == LIST_PARTITION) { uint i; - List_iterator<longlong> list_val_it(p_elem->list_val_list); + List_iterator<part_elem_value> 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) { @@ -1733,8 +1793,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); @@ -2039,26 +2103,15 @@ static inline longlong part_val_int(Item *item_expr) static uint32 calculate_key_value(Field **field_array) { - uint32 hashnr= 0; + ulong nr1= 1; ulong nr2= 4; do { Field *field= *field_array; - if (field->is_null()) - { - hashnr^= (hashnr << 1) | 1; - } - else - { - uint len= field->pack_length(); - ulong nr1= 1; - CHARSET_INFO *cs= field->charset(); - cs->coll->hash_sort(cs, (uchar*)field->ptr, len, &nr1, &nr2); - hashnr^= (uint32)nr1; - } + field->hash(&nr1, &nr2); } while (*(++field_array)); - return hashnr; + return (uint32) nr1; } @@ -2263,15 +2316,16 @@ 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); + longlong list_value; + bool unsigned_flag= part_info->part_expr->unsigned_flag; DBUG_ENTER("get_partition_id_list"); if (part_info->part_expr->null_value) @@ -2284,6 +2338,8 @@ int get_partition_id_list(partition_info *part_info, goto notfound; } *func_value= part_func_value; + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; while (max_list_index >= min_list_index) { list_index= (max_list_index + min_list_index) >> 1; @@ -2350,14 +2406,19 @@ 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; + longlong list_value; /* 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) + part_func_value-= 0x8000000000000000ULL; + 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; @@ -2373,7 +2434,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++; @@ -2391,13 +2452,17 @@ 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); - DBUG_ENTER("get_partition_id_int_range"); + bool unsigned_flag= part_info->part_expr->unsigned_flag; + 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; while (max_part_id > min_part_id) { loc_part_id= (max_part_id + min_part_id + 1) >> 1; @@ -2411,7 +2476,6 @@ int get_partition_id_range(partition_info *part_info, 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 && range_array[loc_part_id] != LONGLONG_MAX && part_func_value >= range_array[loc_part_id]) @@ -2467,13 +2531,16 @@ 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"); + if (unsigned_flag) + part_func_value-= 0x8000000000000000ULL; while (max_part_id > min_part_id) { loc_part_id= (max_part_id + min_part_id + 1) >> 1; @@ -2486,7 +2553,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, if (loc_part_id < max_partition && part_func_value >= range_array[loc_part_id+1]) { - loc_part_id++; + loc_part_id++; } if (left_endpoint) { @@ -3756,14 +3823,13 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info, if (alter_info->flags == ALTER_TABLE_REORG) { uint new_part_no, curr_part_no; - ulonglong max_rows= table->s->max_rows; if (tab_part_info->part_type != HASH_PARTITION || tab_part_info->use_default_no_partitions) { my_error(ER_REORG_NO_PARAM_ERROR, MYF(0)); DBUG_RETURN(TRUE); } - new_part_no= table->file->get_default_no_partitions(max_rows); + new_part_no= table->file->get_default_no_partitions(create_info); curr_part_no= tab_part_info->no_parts; if (new_part_no == curr_part_no) { @@ -4466,7 +4532,7 @@ 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, + if (tab_part_info->check_partition_info(thd, (handlerton**)NULL, table->file, ULL(0))) { DBUG_RETURN(TRUE); @@ -6305,6 +6371,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); |