diff options
author | unknown <mattiasj@client-10-129-10-137.upp.off.mysql.com> | 2008-01-09 13:15:50 +0100 |
---|---|---|
committer | unknown <mattiasj@client-10-129-10-137.upp.off.mysql.com> | 2008-01-09 13:15:50 +0100 |
commit | 1dcf7ed628ca60269042bb73de3d13cc368bccfb (patch) | |
tree | 01efa133afaebe5223ea778383087a1375e03273 /sql/partition_info.cc | |
parent | 190cc349eb171987638087df60faa2cad314ee10 (diff) | |
download | mariadb-git-1dcf7ed628ca60269042bb73de3d13cc368bccfb.tar.gz |
Bug#31931 Partitions: unjustified 'mix of handlers' error message
Problem was that the mix of handlers was not consistent between
CREATE and ALTER
changed so that it works like:
- All partitions must use the same engine
AND it must be the same as the table.
- if one does NOT specify an engine on the table level
then one must either NOT specify any engine on any
partition/subpartition OR for ALL partitions/subpartitions
Note: that after a table have been created, the storage engine
is specified for all parts of the table (table/partition/subpartition)
and so when using alter, one does not need to specify it (unless one
wants to change the storage engine, then one have to specify it on the
table level)
mysql-test/r/partition.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/r/partition_innodb.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/suite/ndb/r/ndb_partition_key.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/suite/ndb/t/ndb_partition_key.test:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test case update
mysql-test/suite/parts/inc/partition_engine.inc:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test case updated
mysql-test/suite/parts/r/ndb_partition_key.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/suite/parts/r/partition_engine_innodb.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/suite/parts/r/partition_engine_myisam.result:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test result updated
mysql-test/suite/parts/t/ndb_partition_key.test:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test case updated
mysql-test/t/partition.test:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test case updated
mysql-test/t/partition_innodb.test:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
test case updated
sql/partition_info.cc:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
moved the check_engine_condition here from sql_partition.cc
created a new check_engine_mix from check_native_partitioned in
sql_partition.cc
sql/partition_info.h:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
non static function check_engine_mix (now used in sql_partition.cc)
sql/sql_partition.cc:
Bug#31931 Partitions: unjustified 'mix of handlers' error message
moved check_engine_condition to partition_info.cc and moved out some
common code in check_native_partitioned to check_engine_mix in
partition_info.cc
Diffstat (limited to 'sql/partition_info.cc')
-rw-r--r-- | sql/partition_info.cc | 247 |
1 files changed, 214 insertions, 33 deletions
diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 3b580422da1..cc7a7f17577 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -419,41 +419,167 @@ char *partition_info::has_unique_names() /* - Check that all partitions use the same storage engine. - This is currently a limitation in this version. + Check that the partition/subpartition is setup to use the correct + storage engine + SYNOPSIS + check_engine_condition() + p_elem Partition element + table_engine_set Have user specified engine on table level + inout::engine_type Current engine used + inout::first Is it first partition + RETURN VALUE + TRUE Failed check + FALSE Ok + DESCRIPTION + Specified engine for table and partitions p0 and pn + Must be correct both on CREATE and ALTER commands + table p0 pn res (0 - OK, 1 - FAIL) + - - - 0 + - - x 1 + - x - 1 + - x x 0 + x - - 0 + x - x 0 + x x - 0 + x x x 0 + i.e: + - All subpartitions must use the same engine + AND it must be the same as the partition. + - All partitions must use the same engine + AND it must be the same as the table. + - if one does NOT specify an engine on the table level + then one must either NOT specify any engine on any + partition/subpartition OR for ALL partitions/subpartitions + Note: + When ALTER a table, the engines are already set for all levels + (table, all partitions and subpartitions). So if one want to + change the storage engine, one must specify it on the table level + +*/ + +static bool check_engine_condition(partition_element *p_elem, + bool table_engine_set, + handlerton **engine_type, + bool *first) +{ + DBUG_ENTER("check_engine_condition"); + + DBUG_PRINT("enter", ("p_eng %u t_eng %u t_eng_set %u first %u state %u", + ha_legacy_type(p_elem->engine_type), + ha_legacy_type(*engine_type), + table_engine_set, *first, p_elem->part_state)); + if (*first && !table_engine_set) + { + *engine_type= p_elem->engine_type; + DBUG_PRINT("info", ("setting table_engine = %u", + ha_legacy_type(*engine_type))); + } + *first= FALSE; + if ((table_engine_set && + (p_elem->engine_type != (*engine_type) && + p_elem->engine_type)) || + (!table_engine_set && + p_elem->engine_type != (*engine_type))) + { + DBUG_RETURN(TRUE); + } + else + { + DBUG_RETURN(FALSE); + } +} + +/* + Check engine mix that it is correct + Current limitation is that all partitions and subpartitions + must use the same storage engine. SYNOPSIS check_engine_mix() - engine_array An array of engine identifiers - no_parts Total number of partitions - + inout::engine_type Current engine used + table_engine_set Have user specified engine on table level RETURN VALUE - TRUE Error, mixed engines - FALSE Ok, no mixed engines + 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. + (specified partition handler ) specified table handler + (NDB, NDB) NDB OK + (MYISAM, MYISAM) - OK + (MYISAM, -) - NOT OK + (MYISAM, -) MYISAM OK + (- , MYISAM) - NOT OK + (- , -) MYISAM OK + (-,-) - OK + (NDB, MYISAM) * NOT OK */ -bool partition_info::check_engine_mix(handlerton **engine_array, uint no_parts) +bool partition_info::check_engine_mix(handlerton *engine_type, + bool table_engine_set) { - uint i= 0; + handlerton *old_engine_type= engine_type; + bool first= TRUE; + uint no_parts= partitions.elements; DBUG_ENTER("partition_info::check_engine_mix"); - - do + DBUG_PRINT("info", ("in: engine_type = %u, table_engine_set = %u", + ha_legacy_type(engine_type), + table_engine_set)); + if (no_parts) { - if (engine_array[i] != engine_array[0]) + List_iterator<partition_element> part_it(partitions); + uint i= 0; + do { - my_error(ER_MIX_HANDLER_ERROR, MYF(0)); - DBUG_RETURN(TRUE); - } - } while (++i < no_parts); - if (engine_array[0]->flags & HTON_NO_PARTITION) + partition_element *part_elem= part_it++; + DBUG_PRINT("info", ("part = %d engine = %d table_engine_set %u", + i, ha_legacy_type(part_elem->engine_type), + table_engine_set)); + if (is_sub_partitioned() && + part_elem->subpartitions.elements) + { + uint no_subparts= part_elem->subpartitions.elements; + uint j= 0; + List_iterator<partition_element> sub_it(part_elem->subpartitions); + do + { + partition_element *sub_elem= sub_it++; + DBUG_PRINT("info", ("sub = %d engine = %u table_engie_set %u", + j, ha_legacy_type(sub_elem->engine_type), + table_engine_set)); + if (check_engine_condition(sub_elem, table_engine_set, + &engine_type, &first)) + goto error; + } while (++j < no_subparts); + /* ensure that the partition also has correct engine */ + if (check_engine_condition(part_elem, table_engine_set, + &engine_type, &first)) + goto error; + } + else if (check_engine_condition(part_elem, table_engine_set, + &engine_type, &first)) + goto error; + } while (++i < no_parts); + } + DBUG_PRINT("info", ("engine_type = %u", + ha_legacy_type(engine_type))); + if (!engine_type) + engine_type= old_engine_type; + if (engine_type->flags & HTON_NO_PARTITION) { my_error(ER_PARTITION_MERGE_ERROR, MYF(0)); DBUG_RETURN(TRUE); } + DBUG_PRINT("info", ("out: engine_type = %u", + ha_legacy_type(engine_type))); + DBUG_ASSERT(engine_type != partition_hton); DBUG_RETURN(FALSE); +error: + /* + Mixed engines not yet supported but when supported it will need + the partition handler + */ + DBUG_RETURN(TRUE); } @@ -726,12 +852,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, bool check_partition_function) { - handlerton **engine_array= NULL; - uint part_count= 0; + handlerton *table_engine= default_engine_type; uint i, tot_partitions; - bool result= TRUE; + bool result= TRUE, table_engine_set; char *same_name; DBUG_ENTER("partition_info::check_partition_info"); + DBUG_ASSERT(default_engine_type != partition_hton); if (check_partition_function) { @@ -777,23 +903,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0)); goto end; } + /* + if NOT specified ENGINE = <engine>: + If Create, always use create_info->db_type + else, use previous tables db_type + either ALL or NONE partition should be set to + default_engine_type when not table_engine_set + Note: after a table is created its storage engines for + the table and all partitions/subpartitions are set. + So when ALTER it is already set on table level + */ + if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE) + { + table_engine_set= TRUE; + table_engine= thd->lex->create_info.db_type; + } + else + { + table_engine_set= FALSE; + if (thd->lex->sql_command != SQLCOM_CREATE_TABLE) + { + table_engine_set= TRUE; + DBUG_ASSERT(table_engine && table_engine != partition_hton); + } + } + 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); + uint no_parts_not_set= 0; + uint prev_no_subparts_not_set= no_subparts + 1; do { partition_element *part_elem= part_it++; if (part_elem->engine_type == NULL) + { + no_parts_not_set++; part_elem->engine_type= default_engine_type; + } if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) part_elem->data_file_name= part_elem->index_file_name= 0; if (!is_sub_partitioned()) @@ -804,13 +956,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, my_error(ER_WRONG_PARTITION_NAME, MYF(0)); goto end; } - DBUG_PRINT("info", ("engine = %d", - ha_legacy_type(part_elem->engine_type))); - engine_array[part_count++]= part_elem->engine_type; + DBUG_PRINT("info", ("part = %d engine = %d", + i, ha_legacy_type(part_elem->engine_type))); } else { uint j= 0; + uint no_subparts_not_set= 0; List_iterator<partition_element> sub_it(part_elem->subpartitions); do { @@ -822,19 +974,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, goto end; } if (sub_elem->engine_type == NULL) + { sub_elem->engine_type= default_engine_type; - DBUG_PRINT("info", ("engine = %u", - ha_legacy_type(sub_elem->engine_type))); - engine_array[part_count++]= sub_elem->engine_type; + no_subparts_not_set++; + } + DBUG_PRINT("info", ("part = %d sub = %d engine = %u", + i, j, ha_legacy_type(sub_elem->engine_type))); } while (++j < no_subparts); + if (prev_no_subparts_not_set == (no_subparts + 1)) + prev_no_subparts_not_set= no_subparts_not_set; + if (!table_engine_set && + prev_no_subparts_not_set == no_subparts_not_set && + no_subparts_not_set != 0 && + no_subparts_not_set != no_subparts) + { + DBUG_PRINT("info", ("no_subparts_not_set = %u no_subparts = %u", + no_subparts_not_set, no_subparts)); + my_error(ER_MIX_HANDLER_ERROR, MYF(0)); + goto end; + } } } while (++i < no_parts); + if (!table_engine_set && + no_parts_not_set != 0 && + no_parts_not_set != no_parts) + { + DBUG_PRINT("info", ("no_parts_not_set = %u no_parts = %u", + no_parts_not_set, no_subparts)); + my_error(ER_MIX_HANDLER_ERROR, MYF(0)); + goto end; + } } - if (unlikely(partition_info::check_engine_mix(engine_array, part_count))) + if (unlikely(check_engine_mix(table_engine, table_engine_set))) + { + my_error(ER_MIX_HANDLER_ERROR, MYF(0)); goto end; + } + if (table_engine == partition_hton) + DBUG_PRINT("info", ("Table engine set to partition_hton")); + DBUG_ASSERT(default_engine_type == table_engine); if (eng_type) - *eng_type= (handlerton*)engine_array[0]; + *eng_type= table_engine; + /* We need to check all constant expressions that they are of the correct @@ -850,7 +1032,6 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } result= FALSE; end: - my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(result); } |