From ee7b76a270684be4a405acbe5d76d13ed37f976e Mon Sep 17 00:00:00 2001 From: Anway Durge Date: Thu, 1 Oct 2026 10:58:14 +0530 Subject: [PATCH] MDEV-41241 I_S.TABLES assert when a function creates a temp table Do not use the fast path when the statement uses a stored routine. Evaluating that function during fill changes THD open-table state and trips restore_backup_open_tables_state(). --- mysql-test/main/mdev_31342.result | 42 +++++++++++++++++++++++++++++++ mysql-test/main/mdev_31342.test | 26 +++++++++++++++++++ sql/sql_show.cc | 10 ++++++++ 3 files changed, 78 insertions(+) diff --git a/mysql-test/main/mdev_31342.result b/mysql-test/main/mdev_31342.result index 9073e469c3e..f7cdd9e0150 100644 --- a/mysql-test/main/mdev_31342.result +++ b/mysql-test/main/mdev_31342.result @@ -983,3 +983,45 @@ WHERE TABLE_SCHEMA='mdev41240' AND TABLE_NAME='t1' TABLE_NAME t1 DROP DATABASE mdev41240; +# +# MDEV-41241: stored function must not assert in get_all_tables +# +CREATE DATABASE mdev41241; +CREATE TABLE mdev41241.t1(a INT); +CREATE TABLE mdev41241.t2(a INT); +CREATE FUNCTION mdev41241.f_ct2(s VARCHAR(64)) RETURNS INT +BEGIN +CREATE TEMPORARY TABLE IF NOT EXISTS mdev41241.ttx(a INT); +RETURN 1; +END// +EXPLAIN FORMAT=JSON SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='mdev41241' AND mdev41241.f_ct2(TABLE_CATALOG)=1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "cost": 0.01423506, + "nested_loop": [ + { + "table": { + "table_name": "TABLES", + "access_type": "ALL", + "key": "TABLE_SCHEMA", + "loops": 1, + "cost": 0.01423506, + "attached_condition": "information_schema.`TABLES`.TABLE_SCHEMA = 'mdev41241' and mdev41241.f_ct2(information_schema.`TABLES`.TABLE_CATALOG) = 1", + "skip_open_table": true, + "scanned_databases": 1 + } + } + ] + } +} +SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='mdev41241' AND mdev41241.f_ct2(TABLE_CATALOG)=1; +TABLE_NAME +t1 +t2 +DROP FUNCTION mdev41241.f_ct2; +DROP TEMPORARY TABLE IF EXISTS mdev41241.ttx; +DROP DATABASE mdev41241; diff --git a/mysql-test/main/mdev_31342.test b/mysql-test/main/mdev_31342.test index a69cbc279e2..6568214e05d 100644 --- a/mysql-test/main/mdev_31342.test +++ b/mysql-test/main/mdev_31342.test @@ -410,3 +410,29 @@ SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mdev41240' AND TABLE_NAME='t1' AND TABLE_NAME IN (SELECT 't1' UNION SELECT 'x'); DROP DATABASE mdev41240; + +--echo # +--echo # MDEV-41241: stored function must not assert in get_all_tables +--echo # +CREATE DATABASE mdev41241; +CREATE TABLE mdev41241.t1(a INT); +CREATE TABLE mdev41241.t2(a INT); +DELIMITER //; +CREATE FUNCTION mdev41241.f_ct2(s VARCHAR(64)) RETURNS INT +BEGIN + CREATE TEMPORARY TABLE IF NOT EXISTS mdev41241.ttx(a INT); + RETURN 1; +END// +DELIMITER ;// +--replace_regex /`tables`/`TABLES`/ /"tables"/"TABLES"/ +EXPLAIN FORMAT=JSON SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='mdev41241' AND mdev41241.f_ct2(TABLE_CATALOG)=1; +# --ps-protocol runs the SELECT twice; the second pass also sees ttx. +--disable_ps_protocol +--sorted_result +SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='mdev41241' AND mdev41241.f_ct2(TABLE_CATALOG)=1; +--enable_ps_protocol +DROP FUNCTION mdev41241.f_ct2; +DROP TEMPORARY TABLE IF EXISTS mdev41241.ttx; +DROP DATABASE mdev41241; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f7fedb2a631..6ead602173b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4283,6 +4283,16 @@ static bool is_simple_is_query(THD *thd) DBUG_PRINT("info", ("subquery in I_S query, using fallback path")); return false; } + /* + A stored function can create tables or otherwise change THD open + table state. get_all_tables() then fails + restore_backup_open_tables_state(). + */ + if (thd->lex->uses_stored_routines()) + { + DBUG_PRINT("info", ("stored routine, using fallback path")); + return false; + } /* Only allow no LIMIT, or LIMIT 1 exactly. Any other explicit LIMIT n is rejected until a general LIMIT implementation is validated.