summaryrefslogtreecommitdiff
path: root/sql/partition_info.cc
diff options
context:
space:
mode:
authorunknown <reggie@linux.site>2006-03-31 11:39:44 -0600
committerunknown <reggie@linux.site>2006-03-31 11:39:44 -0600
commit04570aa5f4d151d50739609a9225d7ae3e0214b2 (patch)
treee6251209765135077322ee23672d32ca66db4791 /sql/partition_info.cc
parent683ce57f452fb08f27a9c089649a8a583f950bfc (diff)
downloadmariadb-git-04570aa5f4d151d50739609a9225d7ae3e0214b2.tar.gz
cleaned up a few method comments
moved several functions from sql_partition to be member functions sql/partition_info.h: move these funcs from sql_partition to this class sql/sql_partition.cc: move these funcs from sql_partition to this class sql/sql_table.cc: calling the member func now instead
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r--sql/partition_info.cc361
1 files changed, 358 insertions, 3 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 10725878d51..ad0aa053ae2 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -124,7 +124,6 @@ char *partition_info::create_default_partition_names(uint part_no, uint no_parts
SYNOPSIS
set_up_default_partitions()
- part_info The reference to all partition information
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
start_no Starting partition number
@@ -201,7 +200,6 @@ end:
SYNOPSIS
set_up_default_subpartitions()
- part_info The reference to all partition information
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
@@ -271,7 +269,6 @@ end:
SYNOPSIS
set_up_defaults_for_partitioning()
- part_info The reference to all partition information
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
start_no Starting partition number
@@ -388,4 +385,362 @@ char *partition_info::has_unique_names()
DBUG_RETURN(NULL);
}
+
+/*
+ Check that all partitions use the same storage engine.
+ This is currently a limitation in this version.
+
+ SYNOPSIS
+ check_engine_mix()
+ engine_array An array of engine identifiers
+ no_parts Total number of partitions
+
+ RETURN VALUE
+ TRUE Error, mixed engines
+ FALSE Ok, no mixed engines
+ DESCRIPTION
+ Current check verifies only that all handlers are the same.
+ Later this check will be more sophisticated.
+*/
+
+bool partition_info::check_engine_mix(handlerton **engine_array, uint no_parts)
+{
+ uint i= 0;
+ bool result= FALSE;
+ DBUG_ENTER("partition_info::check_engine_mix");
+
+ do
+ {
+ if (engine_array[i] != engine_array[0])
+ {
+ result= TRUE;
+ break;
+ }
+ } while (++i < no_parts);
+ DBUG_RETURN(result);
+}
+
+
+/*
+ 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()
+
+ 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()
+{
+ partition_element* part_def;
+ longlong current_largest_int= LONGLONG_MIN;
+ longlong part_range_value_int;
+ uint i;
+ List_iterator<partition_element> it(partitions);
+ bool result= TRUE;
+ DBUG_ENTER("partition_info::check_range_constants");
+ DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts));
+
+ part_result_type= INT_RESULT;
+ range_int_array= (longlong*)sql_alloc(no_parts * sizeof(longlong));
+ if (unlikely(range_int_array == NULL))
+ {
+ mem_alloc_error(no_parts * sizeof(longlong));
+ goto end;
+ }
+ i= 0;
+ do
+ {
+ part_def= it++;
+ if ((i != (no_parts - 1)) || !defined_max_value)
+ part_range_value_int= part_def->range_value;
+ else
+ part_range_value_int= LONGLONG_MAX;
+ if (likely(current_largest_int < part_range_value_int))
+ {
+ current_largest_int= part_range_value_int;
+ range_int_array[i]= part_range_value_int;
+ }
+ else
+ {
+ my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
+ goto end;
+ }
+ } while (++i < no_parts);
+ result= FALSE;
+end:
+ DBUG_RETURN(result);
+}
+
+
+/*
+ A support routine for check_list_constants used by qsort to sort the
+ constant list expressions.
+
+ 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
+*/
+
+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;
+}
+
+
+/*
+ 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()
+
+ 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()
+{
+ uint i;
+ uint list_index= 0;
+ longlong *list_value;
+ bool not_first;
+ bool result= TRUE;
+ longlong curr_value, prev_value;
+ partition_element* part_def;
+ bool found_null= FALSE;
+ List_iterator<partition_element> list_func_it(partitions);
+ DBUG_ENTER("partition_info::check_list_constants");
+
+ part_result_type= INT_RESULT;
+ no_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;
+ }
+ List_iterator<longlong> list_val_it1(part_def->list_val_list);
+ while (list_val_it1++)
+ no_list_values++;
+ } while (++i < no_parts);
+ list_func_it.rewind();
+ list_array= (LIST_PART_ENTRY*)sql_alloc(no_list_values*sizeof(LIST_PART_ENTRY));
+ if (unlikely(list_array == NULL))
+ {
+ mem_alloc_error(no_list_values * sizeof(LIST_PART_ENTRY));
+ goto end;
+ }
+
+ i= 0;
+ do
+ {
+ part_def= list_func_it++;
+ List_iterator<longlong> list_val_it2(part_def->list_val_list);
+ while ((list_value= list_val_it2++))
+ {
+ list_array[list_index].list_value= *list_value;
+ list_array[list_index++].partition_id= i;
+ }
+ } while (++i < no_parts);
+
+ qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
+ &list_part_cmp);
+
+ not_first= FALSE;
+ i= prev_value= 0; //prev_value initialised to quiet compiler
+ do
+ {
+ curr_value= list_array[i].list_value;
+ if (likely(!not_first || prev_value != curr_value))
+ {
+ prev_value= curr_value;
+ not_first= TRUE;
+ }
+ else
+ {
+ my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
+ goto end;
+ }
+ } while (++i < no_list_values);
+ result= FALSE;
+end:
+ DBUG_RETURN(result);
+}
+
+
+/*
+ This code is used early in the CREATE TABLE and ALTER TABLE process.
+
+ SYNOPSIS
+ check_partition_info()
+ file A reference to a handler of the table
+ max_rows Maximum number of rows stored in the table
+ engine_type Return value for used engine in partitions
+
+ RETURN VALUE
+ TRUE Error, something went wrong
+ FALSE Ok, full partition data structures are now generated
+
+ DESCRIPTION
+ We will check that the partition info requested is possible to set-up in
+ this version. This routine is an extension of the parser one could say.
+ If defaults were used we will generate default data structures for all
+ partitions.
+
+*/
+
+bool partition_info::check_partition_info(handlerton **eng_type,
+ handler *file, ulonglong max_rows)
+{
+ handlerton **engine_array= NULL;
+ uint part_count= 0;
+ uint i, tot_partitions;
+ bool result= TRUE;
+ char *same_name;
+ DBUG_ENTER("partition_info::check_partition_info");
+
+ if (unlikely(!is_sub_partitioned() &&
+ !(use_default_subpartitions && use_default_no_subpartitions)))
+ {
+ my_error(ER_SUBPARTITION_ERROR, MYF(0));
+ goto end;
+ }
+ if (unlikely(is_sub_partitioned() &&
+ (!(part_type == RANGE_PARTITION ||
+ part_type == LIST_PARTITION))))
+ {
+ /* Only RANGE and LIST partitioning can be subpartitioned */
+ my_error(ER_SUBPARTITION_ERROR, MYF(0));
+ goto end;
+ }
+ if (unlikely(set_up_defaults_for_partitioning(file, max_rows, (uint)0)))
+ goto end;
+ tot_partitions= get_tot_partitions();
+ if (unlikely(tot_partitions > MAX_PARTITIONS))
+ {
+ my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
+ goto end;
+ }
+ if ((same_name= has_unique_names()))
+ {
+ my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
+ goto end;
+ }
+ engine_array= (handlerton**)my_malloc(tot_partitions * sizeof(handlerton *),
+ MYF(MY_WME));
+ if (unlikely(!engine_array))
+ goto end;
+ i= 0;
+ {
+ List_iterator<partition_element> part_it(partitions);
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (!is_sub_partitioned())
+ {
+ if (part_elem->engine_type == NULL)
+ part_elem->engine_type= default_engine_type;
+ DBUG_PRINT("info", ("engine = %d",
+ ha_legacy_type(part_elem->engine_type)));
+ engine_array[part_count++]= part_elem->engine_type;
+ }
+ else
+ {
+ uint j= 0;
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ do
+ {
+ part_elem= sub_it++;
+ if (part_elem->engine_type == NULL)
+ part_elem->engine_type= default_engine_type;
+ DBUG_PRINT("info", ("engine = %u",
+ ha_legacy_type(part_elem->engine_type)));
+ engine_array[part_count++]= part_elem->engine_type;
+ } while (++j < no_subparts);
+ }
+ } while (++i < no_parts);
+ }
+ if (unlikely(partition_info::check_engine_mix(engine_array, part_count)))
+ {
+ my_error(ER_MIX_HANDLER_ERROR, MYF(0));
+ goto end;
+ }
+
+ if (eng_type)
+ *eng_type= (handlerton*)engine_array[0];
+
+ /*
+ We need to check all constant expressions that they are of the correct
+ type and that they are increasing for ranges and not overlapping for
+ list constants.
+ */
+
+ if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) ||
+ (part_type == LIST_PARTITION && check_list_constants())))
+ goto end;
+ result= FALSE;
+end:
+ my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR));
+ DBUG_RETURN(result);
+}
+
+
#endif /* WITH_PARTITION_STORAGE_ENGINE */