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)
parent 6836db1c
...@@ -536,11 +536,9 @@ t1 CREATE TABLE `t1` ( ...@@ -536,11 +536,9 @@ t1 CREATE TABLE `t1` (
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0, partition p1 engine=heap); (partition p0, partition p1 engine=heap);
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=heap, partition p1); (partition p0 engine=heap, partition p1);
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
alter table t1 alter table t1
engine=heap engine=heap
partition by key (a) partition by key (a)
......
...@@ -79,8 +79,7 @@ engine = innodb ...@@ -79,8 +79,7 @@ engine = innodb
partition by list (a) partition by list (a)
(partition p0 values in (0)); (partition p0 values in (0));
alter table t1 engine = x; alter table t1 engine = x;
Warnings: ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
Warning 1286 Unknown table engine 'x'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
...@@ -151,9 +150,11 @@ DROP TABLE t1; ...@@ -151,9 +150,11 @@ DROP TABLE t1;
create table t1 (int_column int, char_column char(5)) create table t1 (int_column int, char_column char(5))
PARTITION BY RANGE (int_column) subpartition by key (char_column) subpartitions 2 PARTITION BY RANGE (int_column) subpartition by key (char_column) subpartitions 2
(PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB); (PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB);
alter table t1 PARTITION BY RANGE (int_column) alter table t1
ENGINE = MyISAM
PARTITION BY RANGE (int_column)
subpartition by key (char_column) subpartitions 2 subpartition by key (char_column) subpartitions 2
(PARTITION p1 VALUES LESS THAN (5) ENGINE = myisam); (PARTITION p1 VALUES LESS THAN (5));
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
......
...@@ -88,6 +88,12 @@ PARTITION BY KEY(a) ...@@ -88,6 +88,12 @@ PARTITION BY KEY(a)
drop table t1; drop table t1;
CREATE TABLE t1 (a int not null primary key); CREATE TABLE t1 (a int not null primary key);
ALTER TABLE t1 ALTER TABLE t1
ENGINE = NDB
PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1;
CREATE TABLE t1 (a int not null primary key) ENGINE = NDB;
ALTER TABLE t1
PARTITION BY KEY(a) PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB); (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1; drop table t1;
...@@ -143,7 +149,6 @@ t1 CREATE TABLE `t1` ( ...@@ -143,7 +149,6 @@ t1 CREATE TABLE `t1` (
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=ndb, partition p1); (partition p0 engine=ndb, partition p1);
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
alter table t1 alter table t1
engine=ndb engine=ndb
partition by key(a) partition by key(a)
......
...@@ -75,6 +75,14 @@ drop table t1; ...@@ -75,6 +75,14 @@ drop table t1;
CREATE TABLE t1 (a int not null primary key); CREATE TABLE t1 (a int not null primary key);
ALTER TABLE t1 ALTER TABLE t1
ENGINE = NDB
PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1;
CREATE TABLE t1 (a int not null primary key) ENGINE = NDB;
ALTER TABLE t1
PARTITION BY KEY(a) PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB); (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
...@@ -112,7 +120,10 @@ show create table t1; ...@@ -112,7 +120,10 @@ show create table t1;
alter table t1 remove partitioning; alter table t1 remove partitioning;
show create table t1; show create table t1;
--error ER_MIX_HANDLER_ERROR # after bug#31931 was fixed
# this is OK, since the storage engine is specified
# on table level before.
#--error ER_MIX_HANDLER_ERROR
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=ndb, partition p1); (partition p0 engine=ndb, partition p1);
......
...@@ -83,6 +83,7 @@ DROP TABLE t1; ...@@ -83,6 +83,7 @@ DROP TABLE t1;
--echo # 3 Some but not all named partitions or subpartitions get a storage --echo # 3 Some but not all named partitions or subpartitions get a storage
--echo # engine assigned --echo # engine assigned
--echo #------------------------------------------------------------------------ --echo #------------------------------------------------------------------------
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -90,10 +91,7 @@ PARTITION BY HASH(f_int1) ...@@ -90,10 +91,7 @@ PARTITION BY HASH(f_int1)
( PARTITION part1 STORAGE ENGINE = $engine, ( PARTITION part1 STORAGE ENGINE = $engine,
PARTITION part2 PARTITION part2
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) --error ER_MIX_HANDLER_ERROR
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -101,10 +99,7 @@ PARTITION BY HASH(f_int1) ...@@ -101,10 +99,7 @@ PARTITION BY HASH(f_int1)
( PARTITION part1 , ( PARTITION part1 ,
PARTITION part2 STORAGE ENGINE = $engine PARTITION part2 STORAGE ENGINE = $engine
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) --error ER_MIX_HANDLER_ERROR
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -117,10 +112,8 @@ SUBPARTITION BY HASH(f_int1) ...@@ -117,10 +112,8 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine, (SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine) SUBPARTITION subpart22 STORAGE ENGINE = $engine)
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) --echo # this should fail with ER_MIX_HANDLER_ERROR
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template; --echo # after fixing Bug#33722
--source suite/parts/inc/partition_check.inc
DROP TABLE t1;
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -142,6 +135,9 @@ DROP TABLE t1; ...@@ -142,6 +135,9 @@ DROP TABLE t1;
--echo # 4 Storage engine assignment after partition name + after name of --echo # 4 Storage engine assignment after partition name + after name of
--echo # subpartitions belonging to another partition --echo # subpartitions belonging to another partition
--echo #------------------------------------------------------------------------ --echo #------------------------------------------------------------------------
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -154,10 +150,13 @@ SUBPARTITION BY HASH(f_int1) ...@@ -154,10 +150,13 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine, (SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine) SUBPARTITION subpart22 STORAGE ENGINE = $engine)
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) #INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template; #SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc #--source suite/parts/inc/partition_check.inc
DROP TABLE t1; #DROP TABLE t1;
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -170,10 +169,10 @@ SUBPARTITION BY HASH(f_int1) ...@@ -170,10 +169,10 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21, (SUBPARTITION subpart21,
SUBPARTITION subpart22) SUBPARTITION subpart22)
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) #INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template; #SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc #--source suite/parts/inc/partition_check.inc
DROP TABLE t1; #DROP TABLE t1;
# #
--echo #------------------------------------------------------------------------ --echo #------------------------------------------------------------------------
--echo # 5 Precedence of storage engine assignments (if there is any) --echo # 5 Precedence of storage engine assignments (if there is any)
...@@ -210,6 +209,9 @@ DROP TABLE t1; ...@@ -210,6 +209,9 @@ DROP TABLE t1;
--echo # 6.2 Storage engine assignment after partition name + after --echo # 6.2 Storage engine assignment after partition name + after
--echo # subpartition name --echo # subpartition name
# in partition part + in sub partition part # in partition part + in sub partition part
--echo # this should work
--echo # after fixing Bug#33722
--error ER_MIX_HANDLER_ERROR
eval CREATE TABLE t1 ( eval CREATE TABLE t1 (
$column_list $column_list
) )
...@@ -222,10 +224,10 @@ SUBPARTITION BY HASH(f_int1) ...@@ -222,10 +224,10 @@ SUBPARTITION BY HASH(f_int1)
(SUBPARTITION subpart21 STORAGE ENGINE = $engine, (SUBPARTITION subpart21 STORAGE ENGINE = $engine,
SUBPARTITION subpart22 STORAGE ENGINE = $engine) SUBPARTITION subpart22 STORAGE ENGINE = $engine)
); );
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig) #INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template; #SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template;
--source suite/parts/inc/partition_check.inc #--source suite/parts/inc/partition_check.inc
DROP TABLE t1; #DROP TABLE t1;
--echo #------------------------------------------------------------------------ --echo #------------------------------------------------------------------------
--echo # 6 Session default engine differs from engine used within create table --echo # 6 Session default engine differs from engine used within create table
......
...@@ -88,6 +88,12 @@ PARTITION BY KEY(a) ...@@ -88,6 +88,12 @@ PARTITION BY KEY(a)
drop table t1; drop table t1;
CREATE TABLE t1 (a int not null primary key); CREATE TABLE t1 (a int not null primary key);
ALTER TABLE t1 ALTER TABLE t1
ENGINE = NDB
PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1;
CREATE TABLE t1 (a int not null primary key) ENGINE = NDB;
ALTER TABLE t1
PARTITION BY KEY(a) PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB); (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1; drop table t1;
...@@ -143,7 +149,6 @@ t1 CREATE TABLE `t1` ( ...@@ -143,7 +149,6 @@ t1 CREATE TABLE `t1` (
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=ndb, partition p1); (partition p0 engine=ndb, partition p1);
ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL
alter table t1 alter table t1
engine=ndb engine=ndb
partition by key(a) partition by key(a)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -75,6 +75,14 @@ drop table t1; ...@@ -75,6 +75,14 @@ drop table t1;
CREATE TABLE t1 (a int not null primary key); CREATE TABLE t1 (a int not null primary key);
ALTER TABLE t1 ALTER TABLE t1
ENGINE = NDB
PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
drop table t1;
CREATE TABLE t1 (a int not null primary key) ENGINE = NDB;
ALTER TABLE t1
PARTITION BY KEY(a) PARTITION BY KEY(a)
(PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB); (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB);
...@@ -112,7 +120,9 @@ show create table t1; ...@@ -112,7 +120,9 @@ show create table t1;
alter table t1 remove partitioning; alter table t1 remove partitioning;
show create table t1; show create table t1;
--error ER_MIX_HANDLER_ERROR #--error ER_MIX_HANDLER_ERROR
# after fixing bug#31931 this works
# since it already have ndb on table level
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=ndb, partition p1); (partition p0 engine=ndb, partition p1);
......
...@@ -49,6 +49,7 @@ create table t1 (id int auto_increment, s1 int, primary key (id)); ...@@ -49,6 +49,7 @@ create table t1 (id int auto_increment, s1 int, primary key (id));
insert into t1 values (null,1); insert into t1 values (null,1);
insert into t1 values (null,6); insert into t1 values (null,6);
-- sorted_result
select * from t1; select * from t1;
alter table t1 partition by range (id) ( alter table t1 partition by range (id) (
...@@ -618,12 +619,14 @@ partition by key (a) ...@@ -618,12 +619,14 @@ partition by key (a)
(partition p0, partition p1); (partition p0, partition p1);
show create table t1; show create table t1;
--error ER_MIX_HANDLER_ERROR # Since alter, it already have ENGINE=HEAP from before on table level
# -> OK
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0, partition p1 engine=heap); (partition p0, partition p1 engine=heap);
--error ER_MIX_HANDLER_ERROR # Since alter, it already have ENGINE=HEAP from before on table level
# -> OK
alter table t1 alter table t1
partition by key(a) partition by key(a)
(partition p0 engine=heap, partition p1); (partition p0 engine=heap, partition p1);
......
...@@ -86,6 +86,7 @@ engine = innodb ...@@ -86,6 +86,7 @@ engine = innodb
partition by list (a) partition by list (a)
(partition p0 values in (0)); (partition p0 values in (0));
-- error ER_MIX_HANDLER_ERROR
alter table t1 engine = x; alter table t1 engine = x;
show create table t1; show create table t1;
drop table t1; drop table t1;
...@@ -164,8 +165,10 @@ DROP TABLE t1; ...@@ -164,8 +165,10 @@ DROP TABLE t1;
create table t1 (int_column int, char_column char(5)) create table t1 (int_column int, char_column char(5))
PARTITION BY RANGE (int_column) subpartition by key (char_column) subpartitions 2 PARTITION BY RANGE (int_column) subpartition by key (char_column) subpartitions 2
(PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB); (PARTITION p1 VALUES LESS THAN (5) ENGINE = InnoDB);
alter table t1 PARTITION BY RANGE (int_column) alter table t1
ENGINE = MyISAM
PARTITION BY RANGE (int_column)
subpartition by key (char_column) subpartitions 2 subpartition by key (char_column) subpartitions 2
(PARTITION p1 VALUES LESS THAN (5) ENGINE = myisam); (PARTITION p1 VALUES LESS THAN (5));
show create table t1; show create table t1;
drop table t1; drop table t1;
...@@ -419,41 +419,167 @@ char *partition_info::has_unique_names() ...@@ -419,41 +419,167 @@ char *partition_info::has_unique_names()
/* /*
Check that all partitions use the same storage engine. Check that the partition/subpartition is setup to use the correct
This is currently a limitation in this version. 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 SYNOPSIS
check_engine_mix() check_engine_mix()
engine_array An array of engine identifiers inout::engine_type Current engine used
no_parts Total number of partitions table_engine_set Have user specified engine on table level
RETURN VALUE RETURN VALUE
TRUE Error, mixed engines TRUE Error, mixed engines
FALSE Ok, no mixed engines FALSE Ok, no mixed engines
DESCRIPTION DESCRIPTION
Current check verifies only that all handlers are the same. Current check verifies only that all handlers are the same.
Later this check will be more sophisticated. 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"); DBUG_ENTER("partition_info::check_engine_mix");
DBUG_PRINT("info", ("in: engine_type = %u, table_engine_set = %u",
ha_legacy_type(engine_type),
table_engine_set));
if (no_parts)
{
List_iterator<partition_element> part_it(partitions);
uint i= 0;
do do
{ {
if (engine_array[i] != engine_array[0]) 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)
{ {
my_error(ER_MIX_HANDLER_ERROR, MYF(0)); uint no_subparts= part_elem->subpartitions.elements;
DBUG_RETURN(TRUE); 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); } while (++i < no_parts);
if (engine_array[0]->flags & HTON_NO_PARTITION) }
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)); my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
DBUG_PRINT("info", ("out: engine_type = %u",
ha_legacy_type(engine_type)));
DBUG_ASSERT(engine_type != partition_hton);
DBUG_RETURN(FALSE); 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, ...@@ -726,12 +852,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
handler *file, HA_CREATE_INFO *info, handler *file, HA_CREATE_INFO *info,
bool check_partition_function) bool check_partition_function)
{ {
handlerton **engine_array= NULL; handlerton *table_engine= default_engine_type;
uint part_count= 0;
uint i, tot_partitions; uint i, tot_partitions;
bool result= TRUE; bool result= TRUE, table_engine_set;
char *same_name; char *same_name;
DBUG_ENTER("partition_info::check_partition_info"); DBUG_ENTER("partition_info::check_partition_info");
DBUG_ASSERT(default_engine_type != partition_hton);
if (check_partition_function) if (check_partition_function)
{ {
...@@ -777,23 +903,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, ...@@ -777,23 +903,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0)); my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end; 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())) if ((same_name= has_unique_names()))
{ {
my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name); my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
goto end; goto end;
} }
engine_array= (handlerton**)my_malloc(tot_partitions * sizeof(handlerton *),
MYF(MY_WME));
if (unlikely(!engine_array))
goto end;
i= 0; i= 0;
{ {
List_iterator<partition_element> part_it(partitions); List_iterator<partition_element> part_it(partitions);
uint no_parts_not_set= 0;
uint prev_no_subparts_not_set= no_subparts + 1;
do do
{ {
partition_element *part_elem= part_it++; partition_element *part_elem= part_it++;
if (part_elem->engine_type == NULL) if (part_elem->engine_type == NULL)
{
no_parts_not_set++;
part_elem->engine_type= default_engine_type; part_elem->engine_type= default_engine_type;
}
if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
part_elem->data_file_name= part_elem->index_file_name= 0; part_elem->data_file_name= part_elem->index_file_name= 0;
if (!is_sub_partitioned()) if (!is_sub_partitioned())
...@@ -804,13 +956,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, ...@@ -804,13 +956,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error(ER_WRONG_PARTITION_NAME, MYF(0)); my_error(ER_WRONG_PARTITION_NAME, MYF(0));
goto end; goto end;
} }
DBUG_PRINT("info", ("engine = %d", DBUG_PRINT("info", ("part = %d engine = %d",
ha_legacy_type(part_elem->engine_type))); i, ha_legacy_type(part_elem->engine_type)));
engine_array[part_count++]= part_elem->engine_type;
} }
else else
{ {
uint j= 0; uint j= 0;
uint no_subparts_not_set= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions); List_iterator<partition_element> sub_it(part_elem->subpartitions);
do do
{ {
...@@ -822,19 +974,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, ...@@ -822,19 +974,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
goto end; goto end;
} }
if (sub_elem->engine_type == NULL) if (sub_elem->engine_type == NULL)
{
sub_elem->engine_type= default_engine_type; sub_elem->engine_type= default_engine_type;
DBUG_PRINT("info", ("engine = %u", no_subparts_not_set++;
ha_legacy_type(sub_elem->engine_type))); }
engine_array[part_count++]= sub_elem->engine_type; DBUG_PRINT("info", ("part = %d sub = %d engine = %u",
i, j, ha_legacy_type(sub_elem->engine_type)));
} while (++j < no_subparts); } 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); } 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; 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) 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 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, ...@@ -850,7 +1032,6 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
} }
result= FALSE; result= FALSE;
end: end:
my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(result); DBUG_RETURN(result);
} }
......
...@@ -269,7 +269,7 @@ class partition_info : public Sql_alloc ...@@ -269,7 +269,7 @@ class partition_info : public Sql_alloc
bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info, bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info,
uint start_no); uint start_no);
char *has_unique_names(); char *has_unique_names();
static bool check_engine_mix(handlerton **engine_array, uint no_parts); bool check_engine_mix(handlerton *engine_type, bool default_engine);
bool check_range_constants(); bool check_range_constants();
bool check_list_constants(); bool check_list_constants();
bool check_partition_info(THD *thd, handlerton **eng_type, bool check_partition_info(THD *thd, handlerton **eng_type,
......
...@@ -3863,6 +3863,8 @@ bool mysql_unpack_partition(THD *thd, ...@@ -3863,6 +3863,8 @@ bool mysql_unpack_partition(THD *thd,
if (!part_info->default_engine_type) if (!part_info->default_engine_type)
part_info->default_engine_type= default_db_type; part_info->default_engine_type= default_db_type;
DBUG_ASSERT(part_info->default_engine_type == default_db_type); DBUG_ASSERT(part_info->default_engine_type == default_db_type);
DBUG_ASSERT(part_info->default_engine_type->db_type != DB_TYPE_UNKNOWN);
DBUG_ASSERT(part_info->default_engine_type != partition_hton);
{ {
/* /*
...@@ -3996,56 +3998,6 @@ static int fast_end_partition(THD *thd, ulonglong copied, ...@@ -3996,56 +3998,6 @@ static int fast_end_partition(THD *thd, ulonglong copied,
} }
/*
Check engine mix that it is correct
SYNOPSIS
check_engine_condition()
p_elem Partition element
default_engine 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 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
*/
static bool check_engine_condition(partition_element *p_elem,
bool default_engine,
handlerton **engine_type,
bool *first)
{
DBUG_ENTER("check_engine_condition");
DBUG_PRINT("enter", ("def_eng = %u, first = %u", default_engine, *first));
if (*first && default_engine)
{
*engine_type= p_elem->engine_type;
}
*first= FALSE;
if ((!default_engine &&
(p_elem->engine_type != (*engine_type) &&
p_elem->engine_type)) ||
(default_engine &&
p_elem->engine_type != (*engine_type)))
{
DBUG_RETURN(TRUE);
}
else
{
DBUG_RETURN(FALSE);
}
}
/* /*
We need to check if engine used by all partitions can handle We need to check if engine used by all partitions can handle
partitioning natively. partitioning natively.
...@@ -4070,52 +4022,30 @@ static bool check_engine_condition(partition_element *p_elem, ...@@ -4070,52 +4022,30 @@ static bool check_engine_condition(partition_element *p_elem,
static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val, static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val,
partition_info *part_info, THD *thd) partition_info *part_info, THD *thd)
{ {
List_iterator<partition_element> part_it(part_info->partitions); bool table_engine_set;
bool first= TRUE; handlerton *engine_type= part_info->default_engine_type;
bool default_engine;
handlerton *engine_type= create_info->db_type;
handlerton *old_engine_type= engine_type; handlerton *old_engine_type= engine_type;
uint i= 0;
uint no_parts= part_info->partitions.elements;
DBUG_ENTER("check_native_partitioned"); DBUG_ENTER("check_native_partitioned");
default_engine= (create_info->used_fields & HA_CREATE_USED_ENGINE) ? if (create_info->used_fields & HA_CREATE_USED_ENGINE)
FALSE : TRUE;
DBUG_PRINT("info", ("engine_type = %u, default = %u",
ha_legacy_type(engine_type),
default_engine));
if (no_parts)
{ {
do table_engine_set= TRUE;
{ engine_type= create_info->db_type;
partition_element *part_elem= part_it++; }
if (part_info->is_sub_partitioned() && else
part_elem->subpartitions.elements)
{ {
uint no_subparts= part_elem->subpartitions.elements; table_engine_set= FALSE;
uint j= 0; if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
List_iterator<partition_element> sub_it(part_elem->subpartitions);
do
{ {
partition_element *sub_elem= sub_it++; table_engine_set= TRUE;
if (check_engine_condition(sub_elem, default_engine, DBUG_ASSERT(engine_type && engine_type != partition_hton);
&engine_type, &first))
goto error;
} while (++j < no_subparts);
/*
In case of subpartitioning and defaults we allow that only
subparts have specified engines, as long as the parts haven't
specified the wrong engine it's ok.
*/
if (check_engine_condition(part_elem, FALSE,
&engine_type, &first))
goto error;
} }
else if (check_engine_condition(part_elem, default_engine,
&engine_type, &first))
goto error;
} while (++i < no_parts);
} }
DBUG_PRINT("info", ("engine_type = %u, table_engine_set = %u",
ha_legacy_type(engine_type),
table_engine_set));
if (part_info->check_engine_mix(engine_type, table_engine_set))
goto error;
/* /*
All engines are of the same type. Check if this engine supports All engines are of the same type. Check if this engine supports
...@@ -4212,7 +4142,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, ...@@ -4212,7 +4142,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (alter_info->flags == ALTER_TABLE_REORG) if (alter_info->flags & ALTER_TABLE_REORG)
{ {
uint new_part_no, curr_part_no; uint new_part_no, curr_part_no;
if (tab_part_info->part_type != HASH_PARTITION || if (tab_part_info->part_type != HASH_PARTITION ||
...@@ -4538,7 +4468,7 @@ that are reorganised. ...@@ -4538,7 +4468,7 @@ that are reorganised.
tab_part_info->is_auto_partitioned= FALSE; tab_part_info->is_auto_partitioned= FALSE;
} }
} }
else if (alter_info->flags == ALTER_DROP_PARTITION) else if (alter_info->flags & ALTER_DROP_PARTITION)
{ {
/* /*
Drop a partition from a range partition and list partitioning is Drop a partition from a range partition and list partitioning is
...@@ -4742,7 +4672,7 @@ state of p1. ...@@ -4742,7 +4672,7 @@ state of p1.
tab_part_info->is_auto_partitioned= FALSE; tab_part_info->is_auto_partitioned= FALSE;
} }
} }
else if (alter_info->flags == ALTER_REORGANIZE_PARTITION) else if (alter_info->flags & ALTER_REORGANIZE_PARTITION)
{ {
/* /*
Reorganise partitions takes a number of partitions that are next Reorganise partitions takes a number of partitions that are next
...@@ -4923,8 +4853,8 @@ the generated partition syntax in a correct manner. ...@@ -4923,8 +4853,8 @@ the generated partition syntax in a correct manner.
} }
*partition_changed= TRUE; *partition_changed= TRUE;
thd->work_part_info= tab_part_info; thd->work_part_info= tab_part_info;
if (alter_info->flags == ALTER_ADD_PARTITION || if (alter_info->flags & ALTER_ADD_PARTITION ||
alter_info->flags == ALTER_REORGANIZE_PARTITION) alter_info->flags & ALTER_REORGANIZE_PARTITION)
{ {
if (tab_part_info->use_default_subpartitions && if (tab_part_info->use_default_subpartitions &&
!alt_part_info->use_default_subpartitions) !alt_part_info->use_default_subpartitions)
...@@ -5051,13 +4981,21 @@ the generated partition syntax in a correct manner. ...@@ -5051,13 +4981,21 @@ the generated partition syntax in a correct manner.
DBUG_PRINT("info", ("partition changed")); DBUG_PRINT("info", ("partition changed"));
*partition_changed= TRUE; *partition_changed= TRUE;
} }
if (create_info->db_type == partition_hton) /*
Set up partition default_engine_type either from the create_info
or from the previus table
*/
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
part_info->default_engine_type= create_info->db_type;
else
{ {
if (!part_info->default_engine_type) if (table->part_info)
part_info->default_engine_type= table->part_info->default_engine_type; part_info->default_engine_type= table->part_info->default_engine_type;
}
else else
part_info->default_engine_type= create_info->db_type; part_info->default_engine_type= create_info->db_type;
}
DBUG_ASSERT(part_info->default_engine_type &&
part_info->default_engine_type != partition_hton);
if (check_native_partitioned(create_info, &is_native_partitioned, if (check_native_partitioned(create_info, &is_native_partitioned,
part_info, thd)) part_info, thd))
{ {
...@@ -6164,7 +6102,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ...@@ -6164,7 +6102,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
goto err; goto err;
} }
} }
else if (alter_info->flags == ALTER_DROP_PARTITION) else if (alter_info->flags & ALTER_DROP_PARTITION)
{ {
/* /*
Now after all checks and setting state on dropped partitions we can Now after all checks and setting state on dropped partitions we can
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment