mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Bug#56814 Explain + subselect + fulltext crashes server
create_sort_index() function overwrites original JOIN_TAB::type field. At re-execution of subquery overwritten JOIN_TAB::type(JT_ALL) is used instead of JT_FT. It misleads test_if_skip_sort_order() and the function tries to find suitable key for the order that should not be allowed for FULLTEXT(JT_FT) table. The fix is to restore JOIN_TAB strucures for subselect on re-execution for EXPLAIN. Additional fix: Update TABLE::maybe_null field which affects list_contains_unique_index() behaviour as it could have the value(maybe_null==TRUE) based on the assumption that this join is outer (see setup_table_map() func). mysql-test/r/explain.result: test case mysql-test/t/explain.test: test case sql/item_subselect.cc: Make subquery uncacheable in case of EXPLAIN. It allows to keep original JOIN_TAB::type(see JOIN::save_join_tab) and restore it on re-execution. sql/sql_select.cc: -restore JOIN_TAB strucures for subselect on re-execution for EXPLAIN -Update TABLE::maybe_null field as it could have the value(maybe_null==TRUE) based on the assumption that this join is outer(see setup_table_map() func). This change is not related to the crash problem but affects EXPLAIN results in the test case.
This commit is contained in:
parent
127c721cef
commit
d0ac4e2c5a
4 changed files with 106 additions and 5 deletions
|
@ -251,4 +251,50 @@ EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1;
|
|||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref c2,c2_2 c2 10 const,const 3 Using where
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#56814 Explain + subselect + fulltext crashes server
|
||||
#
|
||||
CREATE TABLE t1(f1 VARCHAR(6) NOT NULL,
|
||||
FULLTEXT KEY(f1),UNIQUE(f1));
|
||||
INSERT INTO t1 VALUES ('test');
|
||||
EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 JOIN t1 a ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1));
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY a system NULL NULL NULL NULL 1 Using filesort
|
||||
2 SUBQUERY t1 fulltext f1 f1 0 1 Using where
|
||||
PREPARE stmt FROM
|
||||
'EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 RIGHT OUTER JOIN t1 a
|
||||
ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1))';
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY a system NULL NULL NULL NULL 1 Using filesort
|
||||
2 SUBQUERY t1 fulltext f1 f1 0 1 Using where
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY a system NULL NULL NULL NULL 1 Using filesort
|
||||
2 SUBQUERY t1 fulltext f1 f1 0 1 Using where
|
||||
DEALLOCATE PREPARE stmt;
|
||||
PREPARE stmt FROM
|
||||
'EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 JOIN t1 a
|
||||
ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1))';
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY a system NULL NULL NULL NULL 1 Using filesort
|
||||
2 SUBQUERY t1 fulltext f1 f1 0 1 Using where
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 system NULL NULL NULL NULL 1
|
||||
2 SUBQUERY a system NULL NULL NULL NULL 1 Using filesort
|
||||
2 SUBQUERY t1 fulltext f1 f1 0 1 Using where
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
End of 5.1 tests.
|
||||
|
|
|
@ -228,4 +228,40 @@ EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1;
|
|||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#56814 Explain + subselect + fulltext crashes server
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(f1 VARCHAR(6) NOT NULL,
|
||||
FULLTEXT KEY(f1),UNIQUE(f1));
|
||||
INSERT INTO t1 VALUES ('test');
|
||||
|
||||
EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 JOIN t1 a ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1));
|
||||
|
||||
PREPARE stmt FROM
|
||||
'EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 RIGHT OUTER JOIN t1 a
|
||||
ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1))';
|
||||
|
||||
EXECUTE stmt;
|
||||
EXECUTE stmt;
|
||||
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
PREPARE stmt FROM
|
||||
'EXPLAIN SELECT 1 FROM t1
|
||||
WHERE 1 > ALL((SELECT 1 FROM t1 JOIN t1 a
|
||||
ON (MATCH(t1.f1) AGAINST (""))
|
||||
WHERE t1.f1 GROUP BY t1.f1))';
|
||||
|
||||
EXECUTE stmt;
|
||||
EXECUTE stmt;
|
||||
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.1 tests.
|
||||
|
|
|
@ -1906,21 +1906,26 @@ int subselect_single_select_engine::exec()
|
|||
DBUG_RETURN(join->error ? join->error : 1);
|
||||
}
|
||||
if (!select_lex->uncacheable && thd->lex->describe &&
|
||||
!(join->select_options & SELECT_DESCRIBE) &&
|
||||
join->need_tmp)
|
||||
!(join->select_options & SELECT_DESCRIBE))
|
||||
{
|
||||
item->update_used_tables();
|
||||
if (item->const_item())
|
||||
{
|
||||
/*
|
||||
It's necessary to keep original JOIN table because
|
||||
create_sort_index() function may overwrite original
|
||||
JOIN_TAB::type and wrong optimization method can be
|
||||
selected on re-execution.
|
||||
*/
|
||||
select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
|
||||
select_lex->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
|
||||
/*
|
||||
Force join->join_tmp creation, because this subquery will be replaced
|
||||
by a simple select from the materialization temp table by optimize()
|
||||
called by EXPLAIN and we need to preserve the initial query structure
|
||||
so we can display it.
|
||||
*/
|
||||
select_lex->uncacheable|= UNCACHEABLE_EXPLAIN;
|
||||
select_lex->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
|
||||
if (join->init_save_join_tab())
|
||||
if (join->need_tmp && join->init_save_join_tab())
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2490,6 +2490,13 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
|||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/*
|
||||
Original join tabs might be overwritten at first
|
||||
subselect execution. So we need to restore them.
|
||||
*/
|
||||
Item_subselect *subselect= select_lex->master_unit()->item;
|
||||
if (subselect && subselect->is_uncacheable() && join->reinit())
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -8825,6 +8832,13 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
|||
that reject nulls => the outer join can be replaced by an inner join.
|
||||
*/
|
||||
table->outer_join= 0;
|
||||
/*
|
||||
Update TABLE::maybe_null field as it could have
|
||||
the value(maybe_null==TRUE) based on the assumption
|
||||
that this join is outer(see setup_table_map() func).
|
||||
*/
|
||||
if (table->table)
|
||||
table->table->maybe_null= FALSE;
|
||||
if (table->on_expr)
|
||||
{
|
||||
/* Add on expression to the where condition. */
|
||||
|
|
Loading…
Add table
Reference in a new issue