summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-09-22 13:40:05 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-09-22 13:40:05 +0300
commit3eb81136e1c087af3fef38ae89e3357f4c306f8d (patch)
treed4d9a1aec74040f0531416682c92ade5055eabb2
parente5e83daf32300115d857b49fdbd35460bbf51d52 (diff)
downloadmariadb-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.result10
-rw-r--r--mysql-test/suite/innodb/t/alter_table.test11
-rw-r--r--storage/innobase/handler/handler0alter.cc18
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()) {