mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-41240 I_S.TABLES crash with TABLE_NAME and a subquery
Do not use the fast path when the query has a subquery. Evaluating that predicate while get_all_tables() uses a temporary MEM_ROOT freed the subquery JOIN before outer JOIN cleanup.
This commit is contained in:
committed by
Jan Lindström
parent
9cee6ffa1a
commit
9cdcb266dd
@@ -919,3 +919,67 @@ information_schema.TABLES.TABLE_NAME user user 4 4 0 0 4.0000 NULL ENUM('user')
|
||||
# MDEV-41204: client cursor protocol uses fallback
|
||||
# (also covered by running this test with --cursor-protocol)
|
||||
#
|
||||
#
|
||||
# MDEV-41240: exact TABLE_NAME lookup plus a materialised subquery
|
||||
#
|
||||
CREATE DATABASE mdev41240;
|
||||
CREATE TABLE mdev41240.t1(a INT);
|
||||
EXPLAIN FORMAT=JSON SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA='mdev41240' AND TABLE_NAME='t1'
|
||||
AND TABLE_NAME IN (SELECT 't1' UNION SELECT 'x');
|
||||
EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
"cost": 0.01423506,
|
||||
"nested_loop": [
|
||||
{
|
||||
"table": {
|
||||
"table_name": "TABLES",
|
||||
"access_type": "ALL",
|
||||
"key": "TABLE_SCHEMA,TABLE_NAME",
|
||||
"loops": 1,
|
||||
"cost": 0.01423506,
|
||||
"attached_condition": "information_schema.`TABLES`.TABLE_SCHEMA = 'mdev41240' and information_schema.`TABLES`.`TABLE_NAME` = 't1' and <in_optimizer>(information_schema.`TABLES`.`TABLE_NAME`,<exists>(subquery#2))",
|
||||
"skip_open_table": true,
|
||||
"scanned_databases": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"subqueries": [
|
||||
{
|
||||
"query_block": {
|
||||
"union_result": {
|
||||
"table_name": "<union2,3>",
|
||||
"access_type": "ALL",
|
||||
"query_specifications": [
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 2,
|
||||
"table": {
|
||||
"message": "No tables used"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 3,
|
||||
"operation": "UNION",
|
||||
"table": {
|
||||
"message": "No tables used"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA='mdev41240' AND TABLE_NAME='t1'
|
||||
AND TABLE_NAME IN (SELECT 't1' UNION SELECT 'x');
|
||||
TABLE_NAME
|
||||
t1
|
||||
DROP DATABASE mdev41240;
|
||||
|
||||
@@ -396,3 +396,17 @@ WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME='user' PROCEDURE ANALYSE();
|
||||
--echo # MDEV-41204: client cursor protocol uses fallback
|
||||
--echo # (also covered by running this test with --cursor-protocol)
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-41240: exact TABLE_NAME lookup plus a materialised subquery
|
||||
--echo #
|
||||
CREATE DATABASE mdev41240;
|
||||
CREATE TABLE mdev41240.t1(a INT);
|
||||
--replace_regex /`tables`/`TABLES`/ /"tables"/"TABLES"/
|
||||
EXPLAIN FORMAT=JSON SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA='mdev41240' AND TABLE_NAME='t1'
|
||||
AND TABLE_NAME IN (SELECT 't1' UNION SELECT 'x');
|
||||
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;
|
||||
|
||||
@@ -4272,6 +4272,17 @@ static bool is_simple_is_query(THD *thd)
|
||||
DBUG_PRINT("info", ("SQL_BUFFER_RESULT, using fallback path"));
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
A subquery in WHERE is evaluated from schema_table_store_record()
|
||||
while get_all_tables() may be using a temporary MEM_ROOT. Freeing
|
||||
that root leaves the subquery JOIN dangling.
|
||||
*/
|
||||
if (sel->first_inner_unit() ||
|
||||
(sel->where && sel->where->with_subquery()))
|
||||
{
|
||||
DBUG_PRINT("info", ("subquery in I_S query, 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.
|
||||
|
||||
Reference in New Issue
Block a user