summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/ha_partition.cc2
-rw-r--r--sql/partition_info.cc403
-rw-r--r--sql/partition_info.h15
-rw-r--r--sql/sql_partition.cc422
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))))