From 683ce57f452fb08f27a9c089649a8a583f950bfc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Mar 2006 01:02:44 -0600 Subject: [PATCH 1/2] BUG # 17631 SHOW TABLE STATUS reports wrong engine mysql-test/r/partition.result: results block for bug # 17631 mysql-test/t/partition.test: test block for bug #17631 sql/ha_partition.cc: move table_type func to .cc file and return table_type from the first handler. This is acceptable since we know we have at least one handler and we currently do not support multiple engine types. Later, we'll need to extend this to return some type of delimited list sql/ha_partition.h: removed inline version of this function sql/sql_show.cc: if the table is partitioned, we add the term "partitioned" to the create options. We make sure we are using the partitioned handlerton before we do this. When we support more native partition handlers then this will need to change. --- mysql-test/r/partition.result | 12 +++++++++++- mysql-test/t/partition.test | 13 +++++++++++++ sql/ha_partition.cc | 7 +++++++ sql/ha_partition.h | 3 +-- sql/sql_show.cc | 6 ++++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index f5d8cc8f349..970e5234ca8 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -642,7 +642,7 @@ drop table t1; create table t1 (a int) engine=innodb partition by hash(a) ; show table status like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 PARTITION 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL +t1 InnoDB 10 Compact 2 8192 16384 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned drop table t1; create table t2 (s1 int not null auto_increment, primary key (s1)) partition by list (s1) (partition p1 values in (1),partition p2 values in (2),partition p3 values in (3),partition p4 values in (4)); insert into t2 values (null),(null),(null); @@ -819,4 +819,14 @@ explain partitions select * from t1 where a is null or a < 0 or a > 1; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pn,p2 ALL NULL NULL NULL NULL 2 Using where drop table t1; +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, name VARCHAR(20)) +ENGINE=MyISAM DEFAULT CHARSET=latin1 +PARTITION BY RANGE(id) +(PARTITION p0 VALUES LESS THAN (10) ENGINE = MyISAM, +PARTITION p1 VALUES LESS THAN (20) ENGINE = MyISAM, +PARTITION p2 VALUES LESS THAN (30) ENGINE = MyISAM); +SHOW TABLE STATUS; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Dynamic 0 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index c3e32e832bf..b3a6319643d 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -924,4 +924,17 @@ select * from t1 where a is null or a < 0 or a > 1; explain partitions select * from t1 where a is null or a < 0 or a > 1; drop table t1; +# +#Bug# 17631 SHOW TABLE STATUS reports wrong engine +# +CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, name VARCHAR(20)) +ENGINE=MyISAM DEFAULT CHARSET=latin1 +PARTITION BY RANGE(id) +(PARTITION p0 VALUES LESS THAN (10) ENGINE = MyISAM, +PARTITION p1 VALUES LESS THAN (20) ENGINE = MyISAM, +PARTITION p2 VALUES LESS THAN (30) ENGINE = MyISAM); +--replace_column 6 0 7 0 8 0 9 0 12 NULL 13 NULL 14 NULL +SHOW TABLE STATUS; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0a8f92d6813..cc34ace546a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -257,6 +257,13 @@ void ha_partition::init_handler_variables() } +const char *ha_partition::table_type() const +{ + // we can do this since we only support a single engine type + return m_file[0]->table_type(); +} + + /* Destructor method diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 32ea75fabf0..96b615df71a 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -524,8 +524,7 @@ public: virtual const char *index_type(uint inx); /* The name of the table type that will be used for display purposes */ - virtual const char *table_type() const - { return "PARTITION"; } + virtual const char *table_type() const; /* The name of the row type used for the underlying tables. */ virtual enum row_type get_row_type() const; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index da372d9063d..5c536714222 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2719,6 +2719,12 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) share->row_type], NullS); +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (share->db_type == &partition_hton && + share->partition_info != NULL && + ((partition_info*)share->partition_info)->no_parts > 0) + ptr= strmov(ptr, " partitioned"); +#endif table->field[19]->store(option_buff+1, (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1), cs); From 04570aa5f4d151d50739609a9225d7ae3e0214b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 31 Mar 2006 11:39:44 -0600 Subject: [PATCH 2/2] 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 --- sql/partition_info.cc | 361 ++++++++++++++++++++++++++++++++++++++- sql/partition_info.h | 6 + sql/sql_partition.cc | 387 +----------------------------------------- sql/sql_table.cc | 2 +- 4 files changed, 370 insertions(+), 386 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 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 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 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 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 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 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 */ diff --git a/sql/partition_info.h b/sql/partition_info.h index 69aef512a67..08669f8001e 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -245,7 +245,13 @@ public: bool set_up_defaults_for_partitioning(handler *file, ulonglong max_rows, uint start_no); char *has_unique_names(); + static bool check_engine_mix(handlerton **engine_array, uint no_parts); + bool check_range_constants(); + bool check_list_constants(); + bool check_partition_info(handlerton **eng_type, + handler *file, ulonglong max_rows); private: + static int list_part_cmp(const void* a, const void* b); bool set_up_default_partitions(handler *file, ulonglong max_rows, uint start_no); bool set_up_default_subpartitions(handler *file, ulonglong max_rows); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index d8a886d2227..23436ba05d0 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -410,383 +410,6 @@ int get_part_for_delete(const byte *buf, const byte *rec0, } -/* - 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() - part_info Partition info - - 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(partition_info *part_info) -{ - partition_element* part_def; - longlong current_largest_int= LONGLONG_MIN; - longlong part_range_value_int; - uint no_parts= part_info->no_parts; - uint i; - List_iterator it(part_info->partitions); - bool result= TRUE; - DBUG_ENTER("check_range_constants"); - DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts)); - - part_info->part_result_type= INT_RESULT; - part_info->range_int_array= - (longlong*)sql_alloc(no_parts * sizeof(longlong)); - if (unlikely(part_info->range_int_array == NULL)) - { - mem_alloc_error(no_parts * sizeof(longlong)); - goto end; - } - i= 0; - do - { - part_def= it++; - if ((i != (no_parts - 1)) || !part_info->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; - part_info->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 -*/ - -static int 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() - part_info Partition info - - 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(partition_info *part_info) -{ - uint i, no_parts; - uint no_list_values= 0; - 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 list_func_it(part_info->partitions); - DBUG_ENTER("check_list_constants"); - - part_info->part_result_type= INT_RESULT; - - /* - 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. - */ - - no_parts= part_info->no_parts; - 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; - } - List_iterator list_val_it1(part_def->list_val_list); - while (list_val_it1++) - no_list_values++; - } while (++i < no_parts); - list_func_it.rewind(); - part_info->no_list_values= no_list_values; - part_info->list_array= - (LIST_PART_ENTRY*)sql_alloc(no_list_values*sizeof(LIST_PART_ENTRY)); - if (unlikely(part_info->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 list_val_it2(part_def->list_val_list); - while ((list_value= list_val_it2++)) - { - part_info->list_array[list_index].list_value= *list_value; - part_info->list_array[list_index++].partition_id= i; - } - } while (++i < no_parts); - - qsort((void*)part_info->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= part_info->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); -} - - - - - - - -/* - 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. -*/ - -static bool check_engine_mix(handlerton **engine_array, uint no_parts) -{ - uint i= 0; - bool result= FALSE; - DBUG_ENTER("check_engine_mix"); - - do - { - if (engine_array[i] != engine_array[0]) - { - result= TRUE; - break; - } - } while (++i < no_parts); - DBUG_RETURN(result); -} - - -/* - This code is used early in the CREATE TABLE and ALTER TABLE process. - - SYNOPSIS - check_partition_info() - 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 - 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 check_partition_info(partition_info *part_info,handlerton **eng_type, - handler *file, ulonglong max_rows) -{ - handlerton **engine_array= NULL; - uint part_count= 0; - uint i, no_parts, tot_partitions; - bool result= TRUE; - char *same_name; - DBUG_ENTER("check_partition_info"); - - if (unlikely(!part_info->is_sub_partitioned() && - !(part_info->use_default_subpartitions && - part_info->use_default_no_subpartitions))) - { - my_error(ER_SUBPARTITION_ERROR, MYF(0)); - goto end; - } - if (unlikely(part_info->is_sub_partitioned() && - (!(part_info->part_type == RANGE_PARTITION || - part_info->part_type == LIST_PARTITION)))) - { - /* Only RANGE and LIST partitioning can be subpartitioned */ - my_error(ER_SUBPARTITION_ERROR, MYF(0)); - goto end; - } - if (unlikely(part_info->set_up_defaults_for_partitioning(file, - max_rows, - (uint)0))) - goto end; - tot_partitions= part_info->get_tot_partitions(); - if (unlikely(tot_partitions > MAX_PARTITIONS)) - { - my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0)); - goto end; - } - if ((same_name= part_info->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; - no_parts= part_info->no_parts; - { - List_iterator part_it(part_info->partitions); - do - { - partition_element *part_elem= part_it++; - if (!part_info->is_sub_partitioned()) - { - if (part_elem->engine_type == NULL) - part_elem->engine_type= part_info->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, no_subparts= part_info->no_subparts;; - List_iterator sub_it(part_elem->subpartitions); - do - { - part_elem= sub_it++; - if (part_elem->engine_type == NULL) - part_elem->engine_type= part_info->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 < part_info->no_parts); - } - if (unlikely(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_info->part_type == RANGE_PARTITION && - check_range_constants(part_info)) || - (part_info->part_type == LIST_PARTITION && - check_list_constants(part_info)))) - goto end; - result= FALSE; -end: - my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR)); - DBUG_RETURN(result); -} - - /* This method is used to set-up both partition and subpartitioning field array and used for all types of partitioning. @@ -1814,13 +1437,13 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, if (part_info->part_type == RANGE_PARTITION) { error_str= partition_keywords[PKW_RANGE].str; - if (unlikely(check_range_constants(part_info))) + if (unlikely(part_info->check_range_constants())) goto end; } else if (part_info->part_type == LIST_PARTITION) { error_str= partition_keywords[PKW_LIST].str; - if (unlikely(check_list_constants(part_info))) + if (unlikely(part_info->check_list_constants())) goto end; } else @@ -3638,10 +3261,10 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index, | Forminfo 288 bytes | ------------------------------- | Screen buffer, to make | - | field names readable | + |field names readable | ------------------------------- | Packed field info | - | 17 + 1 + strlen(field_name) | + |17 + 1 + strlen(field_name) | | + 1 end of file character | ------------------------------- | Partition info | @@ -4862,7 +4485,7 @@ the generated partition syntax in a correct manner. tab_part_info->use_default_subpartitions= FALSE; tab_part_info->use_default_no_subpartitions= FALSE; } - if (check_partition_info(tab_part_info, (handlerton**)NULL, + if (tab_part_info->check_partition_info((handlerton**)NULL, table->file, ULL(0))) { DBUG_RETURN(TRUE); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 06e8b3915eb..50dd16e27f2 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2115,7 +2115,7 @@ bool mysql_create_table_internal(THD *thd, } DBUG_PRINT("info", ("db_type = %d", ha_legacy_type(part_info->default_engine_type))); - if (check_partition_info(part_info, &engine_type, file, + if (part_info->check_partition_info( &engine_type, file, create_info->max_rows)) goto err; part_info->default_engine_type= engine_type;