diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-22 13:40:05 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-09-22 13:40:05 +0300 |
commit | 3eb81136e1c087af3fef38ae89e3357f4c306f8d (patch) | |
tree | d4d9a1aec74040f0531416682c92ade5055eabb2 | |
parent | e5e83daf32300115d857b49fdbd35460bbf51d52 (diff) | |
download | mariadb-git-3eb81136e1c087af3fef38ae89e3357f4c306f8d.tar.gz |
MDEV-22939 Server crashes in row_make_new_pathname()
The statement ALTER TABLE...DISCARD TABLESPACE is problematic,
because its designed purpose is to break the referential integrity
of the data dictionary and make a table point to nowhere.
ha_innobase::commit_inplace_alter_table(): Check whether the
table has been discarded. (This is a bit late to check it, right
before committing the change.) Previously, we performed this check
only in a specific branch of the function commit_set_autoinc().
Note: We intentionally allow non-rebuilding ALTER TABLE even if
the tablespace has been discarded, to remain compatible with MySQL.
(See the various tests with "wl5522" in the name, such as
innodb.innodb-wl5522.)
The test case would crash starting with 10.3 only, but it does not hurt
to minimize the code and test difference between 10.2 and 10.3.
-rw-r--r-- | mysql-test/suite/innodb/r/alter_table.result | 10 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/alter_table.test | 11 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 18 |
3 files changed, 30 insertions, 9 deletions
diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index 94262ac29c3..fc08f29e515 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -60,3 +60,13 @@ CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; INSERT INTO t1 SELECT * FROM seq_1_to_128; ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; DROP TABLE t1; +# +# MDEV-22939 Server crashes in row_make_new_pathname() +# +CREATE TABLE t (a INT) ENGINE=INNODB; +ALTER TABLE t DISCARD TABLESPACE; +ALTER TABLE t ENGINE INNODB; +ERROR HY000: Tablespace has been discarded for table `t` +ALTER TABLE t FORCE; +ERROR HY000: Tablespace has been discarded for table `t` +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index 6bc30d2e8ee..5050abdc087 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -68,3 +68,14 @@ CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; INSERT INTO t1 SELECT * FROM seq_1_to_128; ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; DROP TABLE t1; + +--echo # +--echo # MDEV-22939 Server crashes in row_make_new_pathname() +--echo # +CREATE TABLE t (a INT) ENGINE=INNODB; +ALTER TABLE t DISCARD TABLESPACE; +--error ER_TABLESPACE_DISCARDED +ALTER TABLE t ENGINE INNODB; +--error ER_TABLESPACE_DISCARDED +ALTER TABLE t FORCE; +DROP TABLE t; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 09bfc5f5503..f0b12183b22 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7209,12 +7209,6 @@ commit_set_autoinc( && (ha_alter_info->create_info->used_fields & HA_CREATE_USED_AUTO)) { - if (dict_table_is_discarded(ctx->old_table)) { - my_error(ER_TABLESPACE_DISCARDED, MYF(0), - old_table->s->table_name.str); - DBUG_RETURN(true); - } - /* An AUTO_INCREMENT value was supplied by the user. It must be persisted to the data file. */ const Field* ai = old_table->found_next_number_field; @@ -8411,9 +8405,15 @@ ha_innobase::commit_inplace_alter_table( = static_cast<ha_innobase_inplace_ctx*>(*pctx); DBUG_ASSERT(new_clustered == ctx->need_rebuild()); - - fail = commit_set_autoinc(ha_alter_info, ctx, altered_table, - table); + if (ctx->need_rebuild() + && dict_table_is_discarded(ctx->old_table)) { + my_error(ER_TABLESPACE_DISCARDED, MYF(0), + table->s->table_name.str); + fail = true; + } else { + fail = commit_set_autoinc(ha_alter_info, ctx, + altered_table, table); + } if (fail) { } else if (ctx->need_rebuild()) { |