diff options
-rw-r--r-- | sql/ha_partition.cc | 2 | ||||
-rw-r--r-- | sql/partition_info.cc | 403 | ||||
-rw-r--r-- | sql/partition_info.h | 15 | ||||
-rw-r--r-- | sql/sql_partition.cc | 422 |
4 files changed, 403 insertions, 439 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b990baf49fb..9043d56e867 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -8017,7 +8017,7 @@ int ha_partition::compare_number_of_records(ha_partition *me, ::info() is used to return information to the optimizer. Currently this table handler doesn't implement most of the fields really needed. SHOW also makes use of this data - Another note, if your handler doesn't proved exact record count, + Another note, if your handler doesn't provide exact record count, you will probably want to have the following in your code: if (records < 2) records = 2; 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; } diff --git a/sql/partition_info.h b/sql/partition_info.h index f2d185cdfaf..1170aa53e7d 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -27,11 +27,10 @@ class partition_info; struct TABLE_LIST; /* Some function typedefs */ -typedef int (*get_part_id_func)(partition_info *part_info, - uint32 *part_id, +typedef int (*get_part_id_func)(partition_info *part_info, uint32 *part_id, longlong *func_value); -typedef int (*get_subpart_id_func)(partition_info *part_info, - uint32 *part_id); +typedef int (*get_subpart_id_func)(partition_info *part_info, uint32 *part_id); +typedef bool (*check_constants_func)(THD *thd, partition_info *part_info); struct st_ddl_log_memory_entry; @@ -114,6 +113,8 @@ public: get_part_id_func get_part_partition_id_charset; get_subpart_id_func get_subpartition_id_charset; + check_constants_func check_constants; + /* NULL-terminated array of fields used in partitioned expression */ Field **part_field_array; Field **subpart_field_array; @@ -345,8 +346,6 @@ public: const char *find_duplicate_field(); char *find_duplicate_name(); bool check_engine_mix(handlerton *engine_type, bool default_engine); - bool check_range_constants(THD *thd, bool alloc= true); - bool check_list_constants(THD *thd); bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, partition_info *add_or_reorg_part= NULL); @@ -366,7 +365,6 @@ public: part_column_list_val *add_column_value(THD *thd); bool set_part_expr(THD *thd, char *start_token, Item *item_ptr, char *end_token, bool is_subpart); - static int compare_column_values(const void *a, const void *b); bool set_up_charset_field_preps(THD *thd); bool check_partition_field_length(); bool init_column_part(THD *thd); @@ -377,7 +375,6 @@ public: bool has_same_partitioning(partition_info *new_part_info); bool error_if_requires_values() const; private: - static int list_part_cmp(const void* a, const void* b); bool set_up_default_partitions(THD *thd, handler *file, HA_CREATE_INFO *info, uint start_no); bool set_up_default_subpartitions(THD *thd, handler *file, @@ -545,7 +542,7 @@ public: } MEM_ROOT *old_root= thd->mem_root; thd->mem_root= &table->mem_root; - result= check_range_constants(thd, false); + //result= check_range_constants(thd, false); thd->mem_root= old_root; vers_info->stat_serial= table->s->stat_serial; mysql_rwlock_unlock(&table->s->LOCK_stat_serial); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 0839268a0ab..e22f0a7dec9 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1179,6 +1179,386 @@ static void set_up_partition_key_maps(TABLE *table, DBUG_VOID_RETURN; } +static bool check_no_constants(THD *, partition_info*) +{ + return FALSE; +} + +/* + 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; +} + + +/* + Compare two lists of column values in RANGE/LIST partitioning + SYNOPSIS + partition_info_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; +} + + +/* + 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. +*/ + +static bool check_range_constants(THD *thd, partition_info *part_info) +{ + partition_element* part_def; + bool first= TRUE; + uint i; + List_iterator<partition_element> it(part_info->partitions); + bool result= TRUE; + DBUG_ENTER("check_range_constants"); + DBUG_PRINT("enter", ("RANGE with %d parts, column_list = %u", + part_info->num_parts, part_info->column_list)); + + if (part_info->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_info->part_field_list.elements; + uint size_entries= sizeof(part_column_list_val) * num_column_values; + part_info->range_col_array= (part_column_list_val*) + thd->calloc(part_info->num_parts * size_entries); + if (part_info->range_col_array == NULL) + { + mem_alloc_error(part_info->num_parts * size_entries); + goto end; + } + loc_range_col_array= part_info->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 (part_info->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 (partition_info_compare_column_values(current_largest_col_val, + col_val) >= 0) + goto range_not_increasing_error; + } + current_largest_col_val= col_val; + } + first= FALSE; + } while (++i < part_info->num_parts); + } + else + { + longlong UNINIT_VAR(current_largest); + longlong part_range_value; + bool signed_flag= !part_info->part_expr->unsigned_flag; + + part_info->range_int_array= (longlong*) + thd->alloc(part_info->num_parts * sizeof(longlong)); + if (part_info->range_int_array == NULL) + { + mem_alloc_error(part_info->num_parts * sizeof(longlong)); + goto end; + } + i= 0; + do + { + part_def= it++; + if ((i != part_info->num_parts - 1) || !part_info->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 (current_largest > part_range_value || + (current_largest == part_range_value && + (part_range_value < LONGLONG_MAX || + i != part_info->num_parts - 1 || + !part_info->defined_max_value))) + goto range_not_increasing_error; + } + part_info->range_int_array[i]= part_range_value; + current_largest= part_range_value; + first= FALSE; + } while (++i < part_info->num_parts); + } + result= FALSE; +end: + DBUG_RETURN(result); + +range_not_increasing_error: + my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); + goto end; +} + + +/* + 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. +*/ + +static bool check_list_constants(THD *thd, partition_info *part_info) +{ + 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(part_info->partitions); + DBUG_ENTER("check_list_constants"); + + DBUG_ASSERT(part_info->part_type == LIST_PARTITION); + + part_info->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; + } + part_info->has_null_value= TRUE; + part_info->has_null_part_id= i; + found_null= TRUE; + } + part_info->num_list_values+= part_def->list_val_list.elements; + } while (++i < part_info->num_parts); + list_func_it.rewind(); + num_column_values= part_info->part_field_list.elements; + size_entries= part_info->column_list ? + (num_column_values * sizeof(part_column_list_val)) : + sizeof(LIST_PART_ENTRY); + if (!(ptr= thd->calloc((part_info->num_list_values+1) * size_entries))) + goto end; + if (part_info->column_list) + { + part_column_list_val *loc_list_col_array; + loc_list_col_array= (part_column_list_val*)ptr; + part_info->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(part_info->num_list_values); + part_info->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 (part_info->fix_column_value_functions(thd, list_value, i)) + DBUG_RETURN(result); + memcpy(loc_list_col_array, (const void*)col_val, size_entries); + loc_list_col_array+= num_column_values; + } + } while (++i < part_info->num_parts); + } + else + { + compare_func= partition_info_list_part_cmp; + part_info->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_info->part_expr->unsigned_flag ? + 0x8000000000000000ULL : + 0ULL); + + 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(part_info->num_list_values); + part_info->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; + part_info->list_array[list_index].list_value= calc_value; + part_info->list_array[list_index++].partition_id= i; + } + } while (++i < part_info->num_parts); + } + DBUG_ASSERT(part_info->fixed); + if (part_info->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(part_info->list_array, part_info->num_list_values, size_entries, + compare_func); + + i= 0; + do + { + DBUG_ASSERT(i < part_info->num_list_values); + curr_value= part_info->column_list + ? (void*)&part_info->list_col_array[num_column_values * i] + : (void*)&part_info->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 < part_info->num_list_values); + } + result= FALSE; +end: + DBUG_RETURN(result); +} + /* Set up function pointers for partition function @@ -1343,6 +1723,12 @@ static void set_up_partition_func_pointers(partition_info *part_info) part_info->get_subpartition_id; part_info->get_subpartition_id= get_part_id_charset_func_subpart; } + if (part_info->part_type == RANGE_PARTITION) + part_info->check_constants= check_range_constants; + else if (part_info->part_type == LIST_PARTITION) + part_info->check_constants= check_list_constants; + else + part_info->check_constants= check_no_constants; DBUG_VOID_RETURN; } @@ -1506,8 +1892,7 @@ NOTES of an error that is not discovered until here. */ -bool fix_partition_func(THD *thd, TABLE *table, - bool is_create_table_ind) +bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) { bool result= TRUE; partition_info *part_info= table->part_info; @@ -1564,6 +1949,7 @@ bool fix_partition_func(THD *thd, TABLE *table, Partition is defined. We need to verify that partitioning function is correct. */ + set_up_partition_func_pointers(part_info); if (part_info->part_type == HASH_PARTITION) { if (part_info->linear_hash_ind) @@ -1589,7 +1975,6 @@ bool fix_partition_func(THD *thd, TABLE *table, } else { - const char *error_str; if (part_info->column_list) { if (part_info->part_type == VERSIONING_PARTITION && @@ -1606,32 +1991,12 @@ bool fix_partition_func(THD *thd, TABLE *table, goto end; } part_info->fixed= TRUE; - if (part_info->part_type == RANGE_PARTITION) - { - error_str= "HASH"; - if (unlikely(part_info->check_range_constants(thd))) - goto end; - } - else if (part_info->part_type == LIST_PARTITION) - { - error_str= "LIST"; - if (unlikely(part_info->check_list_constants(thd))) - goto end; - } - else if (part_info->part_type == VERSIONING_PARTITION) - { - error_str= "SYSTEM_TIME"; - if (unlikely(part_info->check_range_constants(thd))) - goto end; - } - else - { - DBUG_ASSERT(0); - my_error(ER_INCONSISTENT_PARTITION_INFO_ERROR, MYF(0)); + if (part_info->check_constants(thd, part_info)) goto end; - } if (unlikely(part_info->num_parts < 1)) { + const char *error_str= part_info->part_type == LIST_PARTITION + ? "LIST" : "RANGE"; my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str); goto end; } @@ -1679,7 +2044,6 @@ bool fix_partition_func(THD *thd, TABLE *table, } check_range_capable_PF(table); set_up_partition_key_maps(table, part_info); - set_up_partition_func_pointers(part_info); set_up_range_analysis_info(part_info); table->file->set_part_info(part_info); result= FALSE; @@ -5386,13 +5750,13 @@ the generated partition syntax in a correct manner. tab_part_info->part_type == RANGE_PARTITION && ((is_last_partition_reorged && (tab_part_info->column_list ? - (tab_part_info->compare_column_values( + (partition_info_compare_column_values( alt_max_elem_val->col_val_array, tab_max_elem_val->col_val_array) < 0) : alt_max_range < tab_max_range)) || (!is_last_partition_reorged && (tab_part_info->column_list ? - (tab_part_info->compare_column_values( + (partition_info_compare_column_values( alt_max_elem_val->col_val_array, tab_max_elem_val->col_val_array) != 0) : alt_max_range != tab_max_range)))) |