From 30185c9c7c1e804cd9a8621fe747cb1d159140d7 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 15 Jun 2025 14:27:40 +0300 Subject: [PATCH] MDEV-23207 Assertion `tl->table == __null' failed in THD::open_temporary_table Assertion fails because table is opened by admin_recreate_table(): 71 result_code= (thd->open_temporary_tables(table_list) || 72 mysql_recreate_table(thd, table_list, recreate_info, false)); And that is called because t2 is failed with HA_ADMIN_NOT_IMPLEMENTED: 1093 if (result_code == HA_ADMIN_NOT_IMPLEMENTED && need_repair_or_alter) 1094 { 1095 /* 1096 repair was not implemented and we need to upgrade the table 1097 to a new version so we recreate the table with ALTER TABLE 1098 */ 1099 result_code= admin_recreate_table(thd, table, &recreate_info); 1100 } Actually 'table' is t2 but open_temporary_tables() opens whole list, i.e. t2 and everything what follows it before first_not_own_table(). Therefore t3 is also opened for t2 processing what is wrong. The fix opens exactly one specific table for HA_ADMIN_NOT_IMPLEMENTED. --- mysql-test/main/repair.result | 12 ++++++++++++ mysql-test/main/repair.test | 12 ++++++++++++ sql/sql_admin.cc | 2 +- sql/sql_class.h | 1 + sql/temporary_tables.cc | 11 +++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/repair.result b/mysql-test/main/repair.result index d681db95a74..d0a77ac1aec 100644 --- a/mysql-test/main/repair.result +++ b/mysql-test/main/repair.result @@ -261,4 +261,16 @@ REPAIR TABLE t; Table Op Msg_type Msg_text test.t repair status OK DELETE FROM t; +# +# MDEV-23207 Assertion `tl->table == __null' failed in THD::open_temporary_table +# +create table t1 (pk int primary key) engine=innodb partition by hash(pk) partitions 10; +create table t2 (c int) engine=innodb; +create temporary table t3 (c int); +repair table t1, t2, t3; +Table Op Msg_type Msg_text +test.t1 repair status OK +test.t2 repair status OK +test.t3 repair status OK +drop tables t1, t2; # End of 10.11 tests diff --git a/mysql-test/main/repair.test b/mysql-test/main/repair.test index e0f10a65f77..836134f7f60 100644 --- a/mysql-test/main/repair.test +++ b/mysql-test/main/repair.test @@ -4,6 +4,8 @@ --source include/have_sequence.inc --source include/default_charset.inc +--source include/have_innodb.inc +--source include/have_partition.inc call mtr.add_suppression("character set is multi-byte"); @@ -279,4 +281,14 @@ INSERT INTO t VALUES(1); REPAIR TABLE t; DELETE FROM t; +--echo # +--echo # MDEV-23207 Assertion `tl->table == __null' failed in THD::open_temporary_table +--echo # +create table t1 (pk int primary key) engine=innodb partition by hash(pk) partitions 10; +create table t2 (c int) engine=innodb; +create temporary table t3 (c int); +repair table t1, t2, t3; +drop tables t1, t2; + --echo # End of 10.11 tests + diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index c7f4514d7c8..3b6a73f95c5 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -68,7 +68,7 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list, DEBUG_SYNC(thd, "ha_admin_try_alter"); tmp_disable_binlog(thd); // binlogging is done by caller if wanted - result_code= (thd->open_temporary_tables(table_list) || + result_code= (thd->check_and_open_tmp_table(table_list) || mysql_recreate_table(thd, table_list, recreate_info, false)); reenable_binlog(thd); /* diff --git a/sql/sql_class.h b/sql/sql_class.h index ba690001e9c..3268e6f0c50 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5452,6 +5452,7 @@ public: TMP_TABLE_SHARE *find_tmp_table_share(const char *key, size_t key_length); bool open_temporary_table(TABLE_LIST *tl); + bool check_and_open_tmp_table(TABLE_LIST *tl); bool open_temporary_tables(TABLE_LIST *tl); bool close_temporary_tables(); diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 32e51dbe6a0..eaf6cc88122 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -441,6 +441,17 @@ bool THD::open_temporary_table(TABLE_LIST *tl) } +bool THD::check_and_open_tmp_table(TABLE_LIST *tl) +{ + if (!has_temporary_tables() || + tl == lex->first_not_own_table() || + tl->derived || tl->schema_table) + return false; + + return open_temporary_table(tl); +} + + /** Pre-open temporary tables corresponding to table list elements.