summaryrefslogtreecommitdiff
path: root/sql/partition_info.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2018-02-18 12:24:51 +0100
committerSergei Golubchik <serg@mariadb.org>2018-02-23 15:33:23 +0100
commitc4c81a5b048149c267d92764183cc3dd69def818 (patch)
treeb636a1ad8e9fed21ed40ce6e1a7c9d7f1dadd23c /sql/partition_info.cc
parentf38ef430138fcd67fa8fe354c48c8807e06aaf19 (diff)
downloadmariadb-git-c4c81a5b048149c267d92764183cc3dd69def818.tar.gz
cleanup: partition_info::check_constants
partition_info had a bunch of function pointers to avoid if()'s when invoking part_type specific functionality (like get_part_id, etc). But check_range_constants() and check_list_constants() were still invoked conditionally, with if()'s. Create partition_info::check_constants function pointer, get rid of if()'s Also remove alloc argument of check_range_constants(), added in 26a3ff0a22e. Broken system versioning will be fixed in following commits.
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r--sql/partition_info.cc403
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;
}