MDEV-13788 Server crash when issuing bad SQL partition syntax

This commit is contained in:
Alexander Barkov 2017-11-20 09:33:19 +04:00
parent c44ece7342
commit 9b53e541f0
11 changed files with 165 additions and 20 deletions

View File

@ -0,0 +1,24 @@
--echo #
--echo # MDEV-13788 Server crash when issuing bad SQL partition syntax
--echo #
--eval CREATE TABLE t1 (id int, d date) ENGINE=$engine PARTITION BY RANGE COLUMNS(d) (PARTITION p1 VALUES LESS THAN (MAXVALUE))
SHOW CREATE TABLE t1;
--error ER_PARTITION_REQUIRES_VALUES_ERROR
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
DROP TABLE t1;
--eval CREATE TABLE t1 (id int, d date) ENGINE=$engine PARTITION BY LIST (id) (PARTITION p1 VALUES IN (1,2,3))
SHOW CREATE TABLE t1;
--error ER_PARTITION_REQUIRES_VALUES_ERROR
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES IN (4,5,6)
);
DROP TABLE t1;

View File

@ -0,0 +1,35 @@
#
# MDEV-13788 Server crash when issuing bad SQL partition syntax
#
CREATE TABLE t1 (id int, d date) ENGINE=InnoDB PARTITION BY RANGE COLUMNS(d) (PARTITION p1 VALUES LESS THAN (MAXVALUE));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(d)
(PARTITION p1 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition
DROP TABLE t1;
CREATE TABLE t1 (id int, d date) ENGINE=InnoDB PARTITION BY LIST (id) (PARTITION p1 VALUES IN (1,2,3));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (id)
(PARTITION p1 VALUES IN (1,2,3) ENGINE = InnoDB) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES IN (4,5,6)
);
ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition
DROP TABLE t1;

View File

@ -16,3 +16,38 @@ select * from t1;
pk dt pk dt
1 2017-09-28 15:12:00 1 2017-09-28 15:12:00
drop table t1; drop table t1;
#
# MDEV-13788 Server crash when issuing bad SQL partition syntax
#
CREATE TABLE t1 (id int, d date) ENGINE=Aria PARTITION BY RANGE COLUMNS(d) (PARTITION p1 VALUES LESS THAN (MAXVALUE));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(d)
(PARTITION p1 VALUES LESS THAN (MAXVALUE) ENGINE = Aria) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition
DROP TABLE t1;
CREATE TABLE t1 (id int, d date) ENGINE=Aria PARTITION BY LIST (id) (PARTITION p1 VALUES IN (1,2,3));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (id)
(PARTITION p1 VALUES IN (1,2,3) ENGINE = Aria) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES IN (4,5,6)
);
ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition
DROP TABLE t1;

View File

@ -0,0 +1,35 @@
#
# MDEV-13788 Server crash when issuing bad SQL partition syntax
#
CREATE TABLE t1 (id int, d date) ENGINE=MyISAM PARTITION BY RANGE COLUMNS(d) (PARTITION p1 VALUES LESS THAN (MAXVALUE));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(d)
(PARTITION p1 VALUES LESS THAN (MAXVALUE) ENGINE = MyISAM) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES LESS THAN (MAXVALUE)
);
ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition
DROP TABLE t1;
CREATE TABLE t1 (id int, d date) ENGINE=MyISAM PARTITION BY LIST (id) (PARTITION p1 VALUES IN (1,2,3));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) DEFAULT NULL,
`d` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (id)
(PARTITION p1 VALUES IN (1,2,3) ENGINE = MyISAM) */
ALTER TABLE t1 REORGANIZE PARTITION p1 INTO
(
PARTITION p2, /* Notice no values */
PARTITION p3 VALUES IN (4,5,6)
);
ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition
DROP TABLE t1;

View File

@ -0,0 +1,4 @@
--source include/have_innodb.inc
--source include/have_partition.inc
--let $engine=InnoDB
--source inc/part_alter_values.inc

View File

@ -16,3 +16,6 @@ select * from t1;
alter table t1 drop partition p20181231; alter table t1 drop partition p20181231;
select * from t1; select * from t1;
drop table t1; drop table t1;
--let $engine=Aria
--source inc/part_alter_values.inc

View File

@ -0,0 +1,3 @@
--source include/have_partition.inc
--let $engine=MyISAM
--source inc/part_alter_values.inc

View File

@ -2132,6 +2132,24 @@ end:
DBUG_RETURN(result); DBUG_RETURN(result);
} }
bool partition_info::error_if_requires_values() const
{
switch (part_type) {
case NOT_A_PARTITION:
case HASH_PARTITION:
break;
case RANGE_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
return true;
case LIST_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
return true;
}
return false;
}
/* /*
The parser generates generic data structures, we need to set them up The parser generates generic data structures, we need to set them up
as the rest of the code expects to find them. This is in reality part as the rest of the code expects to find them. This is in reality part
@ -2221,6 +2239,8 @@ int partition_info::fix_parser_data(THD *thd)
part_elem= it++; part_elem= it++;
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list); List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
num_elements= part_elem->list_val_list.elements; num_elements= part_elem->list_val_list.elements;
if (!num_elements && error_if_requires_values())
DBUG_RETURN(true);
DBUG_ASSERT(part_type == RANGE_PARTITION ? DBUG_ASSERT(part_type == RANGE_PARTITION ?
num_elements == 1U : TRUE); num_elements == 1U : TRUE);
for (j= 0; j < num_elements; j++) for (j= 0; j < num_elements; j++)

View File

@ -313,6 +313,7 @@ public:
void set_show_version_string(String *packet); void set_show_version_string(String *packet);
void report_part_expr_error(bool use_subpart_expr); void report_part_expr_error(bool use_subpart_expr);
bool has_same_partitioning(partition_info *new_part_info); bool has_same_partitioning(partition_info *new_part_info);
bool error_if_requires_values() const;
private: private:
static int list_part_cmp(const void* a, const void* b); static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info, bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,

View File

@ -4770,16 +4770,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"LIST", "IN"); "LIST", "IN");
} }
else if (tab_part_info->part_type == RANGE_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
}
else else
{ {
DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION); DBUG_ASSERT(tab_part_info->part_type == RANGE_PARTITION ||
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), tab_part_info->part_type == LIST_PARTITION);
"LIST", "IN"); (void) tab_part_info->error_if_requires_values();
} }
goto err; goto err;
} }

View File

@ -4679,18 +4679,8 @@ opt_part_values:
partition_info *part_info= lex->part_info; partition_info *part_info= lex->part_info;
if (! lex->is_partition_management()) if (! lex->is_partition_management())
{ {
if (part_info->part_type == RANGE_PARTITION) if (part_info->error_if_requires_values())
{ MYSQL_YYABORT;
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
MYSQL_YYABORT;
}
if (part_info->part_type == LIST_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"LIST", "IN");
MYSQL_YYABORT;
}
} }
else else
part_info->part_type= HASH_PARTITION; part_info->part_type= HASH_PARTITION;