diff options
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r-- | sql/partition_info.cc | 403 |
1 files changed, 3 insertions, 400 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 618c866a3b9..2bef5bbb25b 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1514,400 +1514,6 @@ error: } -/* - This routine allocates an array for all range constants to achieve a fast - check what partition a certain value belongs to. At the same time it does - also check that the range constants are defined in increasing order and - that the expressions are constant integer expressions. - - SYNOPSIS - check_range_constants() - thd Thread object - - RETURN VALUE - TRUE An error occurred during creation of range constants - FALSE Successful creation of range constant mapping - - DESCRIPTION - This routine is called from check_partition_info to get a quick error - before we came too far into the CREATE TABLE process. It is also called - from fix_partition_func every time we open the .frm file. It is only - called for RANGE PARTITIONed tables. -*/ - -bool partition_info::check_range_constants(THD *thd, bool alloc) -{ - partition_element* part_def; - bool first= TRUE; - uint i; - List_iterator<partition_element> it(partitions); - int result= TRUE; - DBUG_ENTER("partition_info::check_range_constants"); - DBUG_PRINT("enter", ("RANGE with %d parts, column_list = %u", num_parts, - column_list)); - - if (column_list) - { - part_column_list_val *loc_range_col_array; - part_column_list_val *UNINIT_VAR(current_largest_col_val); - uint num_column_values= part_field_list.elements; - uint size_entries= sizeof(part_column_list_val) * num_column_values; - if (alloc) - { - range_col_array= (part_column_list_val*) thd->calloc(num_parts * - size_entries); - if (unlikely(range_col_array == NULL)) - { - mem_alloc_error(num_parts * size_entries); - goto end; - } - } - loc_range_col_array= range_col_array; - i= 0; - do - { - part_def= it++; - { - List_iterator<part_elem_value> list_val_it(part_def->list_val_list); - part_elem_value *range_val= list_val_it++; - part_column_list_val *col_val= range_val->col_val_array; - - if (fix_column_value_functions(thd, range_val, i)) - goto end; - memcpy(loc_range_col_array, (const void*)col_val, size_entries); - loc_range_col_array+= num_column_values; - if (!first) - { - if (compare_column_values((const void*)current_largest_col_val, - (const void*)col_val) >= 0) - goto range_not_increasing_error; - } - current_largest_col_val= col_val; - } - first= FALSE; - } while (++i < num_parts); - } - else - { - longlong UNINIT_VAR(current_largest); - longlong part_range_value; - bool signed_flag= !part_expr->unsigned_flag; - - if (alloc) - { - range_int_array= (longlong*) thd->alloc(num_parts * sizeof(longlong)); - if (unlikely(range_int_array == NULL)) - { - mem_alloc_error(num_parts * sizeof(longlong)); - goto end; - } - } - i= 0; - do - { - part_def= it++; - if ((i != (num_parts - 1)) || !defined_max_value) - { - part_range_value= part_def->range_value; - if (!signed_flag) - part_range_value-= 0x8000000000000000ULL; - } - else - part_range_value= LONGLONG_MAX; - - if (!first) - { - if (unlikely(current_largest > part_range_value) || - (unlikely(current_largest == part_range_value) && - (part_range_value < LONGLONG_MAX || - i != (num_parts - 1) || - !defined_max_value))) - goto range_not_increasing_error; - } - range_int_array[i]= part_range_value; - current_largest= part_range_value; - first= FALSE; - } while (++i < num_parts); - } - result= FALSE; -end: - DBUG_RETURN(result); - -range_not_increasing_error: - my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); - goto end; -} - - -/* - Support routines for check_list_constants used by qsort to sort the - constant list expressions. One routine for integers and one for - column lists. - - SYNOPSIS - list_part_cmp() - a First list constant to compare with - b Second list constant to compare with - - RETURN VALUE - +1 a > b - 0 a == b - -1 a < b -*/ - -extern "C" -int partition_info_list_part_cmp(const void* a, const void* b) -{ - longlong a1= ((LIST_PART_ENTRY*)a)->list_value; - longlong b1= ((LIST_PART_ENTRY*)b)->list_value; - if (a1 < b1) - return -1; - else if (a1 > b1) - return +1; - else - return 0; -} - - -int partition_info::list_part_cmp(const void* a, const void* b) -{ - return partition_info_list_part_cmp(a, b); -} - - -/* - Compare two lists of column values in RANGE/LIST partitioning - SYNOPSIS - compare_column_values() - first First column list argument - second Second column list argument - RETURN VALUES - 0 Equal - -1 First argument is smaller - +1 First argument is larger -*/ - -extern "C" -int partition_info_compare_column_values(const void *first_arg, - const void *second_arg) -{ - const part_column_list_val *first= (part_column_list_val*)first_arg; - const part_column_list_val *second= (part_column_list_val*)second_arg; - partition_info *part_info= first->part_info; - Field **field; - - for (field= part_info->part_field_array; *field; - field++, first++, second++) - { - if (first->max_value || second->max_value) - { - if (first->max_value && second->max_value) - return 0; - if (second->max_value) - return -1; - else - return +1; - } - if (first->null_value || second->null_value) - { - if (first->null_value && second->null_value) - continue; - if (second->null_value) - return +1; - else - return -1; - } - int res= (*field)->cmp((const uchar*)first->column_value, - (const uchar*)second->column_value); - if (res) - return res; - } - return 0; -} - - -int partition_info::compare_column_values(const void *first_arg, - const void *second_arg) -{ - return partition_info_compare_column_values(first_arg, second_arg); -} - - -/* - This routine allocates an array for all list constants to achieve a fast - check what partition a certain value belongs to. At the same time it does - also check that there are no duplicates among the list constants and that - that the list expressions are constant integer expressions. - - SYNOPSIS - check_list_constants() - thd Thread object - - RETURN VALUE - TRUE An error occurred during creation of list constants - FALSE Successful creation of list constant mapping - - DESCRIPTION - This routine is called from check_partition_info to get a quick error - before we came too far into the CREATE TABLE process. It is also called - from fix_partition_func every time we open the .frm file. It is only - called for LIST PARTITIONed tables. -*/ - -bool partition_info::check_list_constants(THD *thd) -{ - uint i, size_entries, num_column_values; - uint list_index= 0; - part_elem_value *list_value; - bool result= TRUE; - longlong type_add, calc_value; - void *curr_value; - void *UNINIT_VAR(prev_value); - partition_element* part_def; - bool found_null= FALSE; - qsort_cmp compare_func; - void *ptr; - List_iterator<partition_element> list_func_it(partitions); - DBUG_ENTER("partition_info::check_list_constants"); - - DBUG_ASSERT(part_type == LIST_PARTITION); - - num_list_values= 0; - /* - We begin by calculating the number of list values that have been - defined in the first step. - - We use this number to allocate a properly sized array of structs - to keep the partition id and the value to use in that partition. - In the second traversal we assign them values in the struct array. - - Finally we sort the array of structs in order of values to enable - a quick binary search for the proper value to discover the - partition id. - After sorting the array we check that there are no duplicates in the - list. - */ - - i= 0; - do - { - part_def= list_func_it++; - if (part_def->has_null_value) - { - if (found_null) - { - my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); - goto end; - } - has_null_value= TRUE; - has_null_part_id= i; - found_null= TRUE; - } - num_list_values+= part_def->list_val_list.elements; - } while (++i < num_parts); - list_func_it.rewind(); - num_column_values= part_field_list.elements; - size_entries= column_list ? - (num_column_values * sizeof(part_column_list_val)) : - sizeof(LIST_PART_ENTRY); - if (unlikely(!(ptr= thd->calloc((num_list_values+1) * size_entries)))) - goto end; - if (column_list) - { - part_column_list_val *loc_list_col_array; - loc_list_col_array= (part_column_list_val*)ptr; - list_col_array= (part_column_list_val*)ptr; - compare_func= partition_info_compare_column_values; - i= 0; - do - { - part_def= list_func_it++; - if (part_def->max_value) - { - // DEFAULT is not a real value so let's exclude it from sorting. - DBUG_ASSERT(num_list_values); - num_list_values--; - continue; - } - List_iterator<part_elem_value> list_val_it2(part_def->list_val_list); - while ((list_value= list_val_it2++)) - { - part_column_list_val *col_val= list_value->col_val_array; - if (unlikely(fix_column_value_functions(thd, list_value, i))) - { - DBUG_RETURN(TRUE); - } - memcpy(loc_list_col_array, (const void*)col_val, size_entries); - loc_list_col_array+= num_column_values; - } - } while (++i < num_parts); - } - else - { - compare_func= partition_info_list_part_cmp; - list_array= (LIST_PART_ENTRY*)ptr; - 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++; - if (part_def->max_value && part_type == LIST_PARTITION) - { - // DEFAULT is not a real value so let's exclude it from sorting. - DBUG_ASSERT(num_list_values); - num_list_values--; - continue; - } - List_iterator<part_elem_value> list_val_it2(part_def->list_val_list); - while ((list_value= list_val_it2++)) - { - calc_value= list_value->value - type_add; - list_array[list_index].list_value= calc_value; - list_array[list_index++].partition_id= i; - } - } while (++i < num_parts); - } - DBUG_ASSERT(fixed); - if (num_list_values) - { - bool first= TRUE; - /* - list_array and list_col_array are unions, so this works for both - variants of LIST partitioning. - */ - my_qsort((void*)list_array, num_list_values, size_entries, - compare_func); - - i= 0; - do - { - DBUG_ASSERT(i < num_list_values); - curr_value= column_list ? (void*)&list_col_array[num_column_values * i] : - (void*)&list_array[i]; - if (likely(first || compare_func(curr_value, prev_value))) - { - prev_value= curr_value; - first= FALSE; - } - else - { - my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); - goto end; - } - } while (++i < num_list_values); - } - result= FALSE; -end: - DBUG_RETURN(result); -} - /** Check if we allow DATA/INDEX DIRECTORY, if not warn and set them to NULL. @@ -2227,10 +1833,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, if (unlikely(part_type == VERSIONING_PARTITION && vers_setup_expression(thd, add_or_reorg_part->partitions.elements))) goto end; - if (unlikely(((part_type == RANGE_PARTITION || part_type == VERSIONING_PARTITION) && - check_range_constants(thd)) || - (part_type == LIST_PARTITION && - check_list_constants(thd)))) + if (check_constants(thd, this)) goto end; } @@ -2978,8 +2581,7 @@ bool partition_info::fix_column_value_functions(THD *thd, sql_mode_t save_sql_mode; bool save_got_warning; - if (!(column_item= get_column_item(column_item, - field))) + if (!(column_item= get_column_item(column_item, field))) { result= TRUE; goto end; @@ -2992,6 +2594,7 @@ bool partition_info::fix_column_value_functions(THD *thd, thd->got_warning) { my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); + thd->variables.sql_mode= save_sql_mode; result= TRUE; goto end; } |