Commit dea5746d authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-32155 MariaDB Server crashes with ill-formed partitions

for ALTER_PARTITION_ADMIN (CHECK/REPAIR/LOAD INDEX/CACHE INDEX/etc)
partitioning marks affected partitions with PART_ADMIN state.

The assumption is that the server will call a corresponding
method of ha_partition which will reset the state back to PART_NORMAL.

This assumption is invalid, the server is not required to do so,
indeed, in CHECK ... FOR UPGRADE the server might decide early that
the table is fine and won't call ha_partition::check(), leaving
partitions in the wrong state. It will thus leak into the next
statement confusing the engine about what it is doing (see
ha_partition::create_handler_file()), causing a crash later.

Let's force all partitions into PART_NORMAL state after the admin
operation succeeded, in case it did so without consulting the engine.
parent 8ac30517
DROP TABLE IF EXISTS t1, t2, v, x;
# Actual test of key caches # Actual test of key caches
# Verifing that reads/writes use the key cache correctly # Verifing that reads/writes use the key cache correctly
SET @org_key_cache_buffer_size= @@global.default.key_buffer_size; SET @org_key_cache_buffer_size= @@global.default.key_buffer_size;
......
# Test of key cache with partitions # Test of key cache with partitions
--source include/have_partition.inc --source include/have_partition.inc
--disable_warnings
DROP TABLE IF EXISTS t1, t2, v, x;
--enable_warnings
--echo # Actual test of key caches --echo # Actual test of key caches
--echo # Verifing that reads/writes use the key cache correctly --echo # Verifing that reads/writes use the key cache correctly
SET @org_key_cache_buffer_size= @@global.default.key_buffer_size; SET @org_key_cache_buffer_size= @@global.default.key_buffer_size;
......
drop table if exists t1;
CREATE TABLE t1 (a int, b int) CREATE TABLE t1 (a int, b int)
PARTITION BY RANGE (a) PARTITION BY RANGE (a)
(PARTITION x0 VALUES LESS THAN (2), (PARTITION x0 VALUES LESS THAN (2),
...@@ -158,3 +157,15 @@ PARTITION p1 VALUES IN (0) (SUBPARTITION p1b), ...@@ -158,3 +157,15 @@ PARTITION p1 VALUES IN (0) (SUBPARTITION p1b),
PARTITION p2 VALUES IN (2) (SUBPARTITION p1b) PARTITION p2 VALUES IN (2) (SUBPARTITION p1b)
); );
ERROR HY000: Duplicate partition name p1b ERROR HY000: Duplicate partition name p1b
# End of 5.5 tests
#
# MDEV-32155 MariaDB Server crashes with ill-formed partitions
#
create table t1 (c1 set ( 'abc' ) binary unicode) partition by linear hash (c1 mod c1) partitions 10;
alter table t1 check partition all for upgrade;
Table Op Msg_type Msg_text
test.t1 check status OK
alter table t1 order by nonexistent;
ERROR 42S22: Unknown column 'nonexistent' in 'order clause'
drop table t1;
# End of 10.5 tests
...@@ -4,10 +4,6 @@ ...@@ -4,10 +4,6 @@
# #
-- source include/have_partition.inc -- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
# #
# Try faulty DROP PARTITION and COALESCE PARTITION # Try faulty DROP PARTITION and COALESCE PARTITION
# #
...@@ -223,3 +219,16 @@ SUBPARTITION BY KEY (s2) ( ...@@ -223,3 +219,16 @@ SUBPARTITION BY KEY (s2) (
PARTITION p1 VALUES IN (0) (SUBPARTITION p1b), PARTITION p1 VALUES IN (0) (SUBPARTITION p1b),
PARTITION p2 VALUES IN (2) (SUBPARTITION p1b) PARTITION p2 VALUES IN (2) (SUBPARTITION p1b)
); );
--echo # End of 5.5 tests
--echo #
--echo # MDEV-32155 MariaDB Server crashes with ill-formed partitions
--echo #
create table t1 (c1 set ( 'abc' ) binary unicode) partition by linear hash (c1 mod c1) partitions 10;
alter table t1 check partition all for upgrade;
--error ER_BAD_FIELD_ERROR
alter table t1 order by nonexistent;
drop table t1;
--echo # End of 10.5 tests
...@@ -875,6 +875,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -875,6 +875,10 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
result_code = (table->table->file->*operator_func)(thd, check_opt); result_code = (table->table->file->*operator_func)(thd, check_opt);
THD_STAGE_INFO(thd, stage_sending_data); THD_STAGE_INFO(thd, stage_sending_data);
DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (lex->alter_info.partition_flags & ALTER_PARTITION_ADMIN)
set_part_state(&lex->alter_info, table->table->part_info, PART_NORMAL);
#endif
} }
if (compl_result_code == HA_ADMIN_OK && collect_eis) if (compl_result_code == HA_ADMIN_OK && collect_eis)
......
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