Skip to content

Commit 9f64b29

Browse files
MDEV-32397, MDEV-32403 Crashes during join processing.
Queries having the following form may cause a crash SELECT t1.a FROM ( SELECT a AS a1 FROM t1 ) dt JOIN t1 ON a1 LIKE EXISTS ( SELECT a + RAND () FROM t1 UNION SELECT a FROM t1); because the table t1 has some JOIN cleanup operations performed prematurely during the subselect. In this particular case, the presence of RAND() makes the subquery uncacheable, necessitating the need to execute the subquery multiple times during join record evaluation. Each time the subquery runs, it creates its own JOIN structure which has references to the table t1. When the subquery completes, JOIN::cleanup and functions called by it result in ha_end_keyread() being called on table t1. However, we are not done with table t1 because the upper level `select t1.a from...` query requires table t1 to be open. To solve this, we make the executor aware of when we're in subqueries like this and delay JOIN cleanup until the end of the query.
1 parent cf249ca commit 9f64b29

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CREATE TABLE t1 ( a double, key (a)) ;
2+
INSERT INTO t1 VALUES (1),(2),(-3);
3+
SELECT t1.a FROM ( SELECT a AS a1 FROM t1 ) dt
4+
JOIN t1 ON a1 LIKE EXISTS ( SELECT a + RAND () FROM t1 UNION SELECT a FROM t1) ;
5+
DROP TABLE t1;
6+
CREATE TABLE t1 ( a VARCHAR(100), b bool) ;
7+
INSERT INTO t1 VALUES ('-101',-87),('-95',59),(NULL,48);
8+
SELECT
9+
(SELECT 1 FROM (SELECT 1 HAVING rand() ) dt1
10+
UNION
11+
SELECT a FROM t1 WHERE b IN (SELECT a FROM t1) LIMIT 1)
12+
FROM t1;
13+
DROP TABLE t1;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# MDEV-32397 join_read_first, keyread SEGV crash
3+
#
4+
CREATE TABLE t1 ( a double, key (a)) ;
5+
INSERT INTO t1 VALUES (1),(2),(-3);
6+
# We disable the result log because RAND() is unpredictable and seeding RAND
7+
# doesn't make it stable when using the PS protocol.
8+
--disable_result_log
9+
SELECT t1.a FROM ( SELECT a AS a1 FROM t1 ) dt
10+
JOIN t1 ON a1 LIKE EXISTS ( SELECT a + RAND () FROM t1 UNION SELECT a FROM t1) ;
11+
--enable_result_log
12+
DROP TABLE t1;
13+
14+
#
15+
# MDEV-32403 test_if_quick_select: Segv
16+
#
17+
CREATE TABLE t1 ( a VARCHAR(100), b bool) ;
18+
INSERT INTO t1 VALUES ('-101',-87),('-95',59),(NULL,48);
19+
# We disable the result log because RAND() is unpredictable and seeding RAND
20+
# doesn't make it stable when using the PS protocol.
21+
--disable_result_log
22+
SELECT
23+
(SELECT 1 FROM (SELECT 1 HAVING rand() ) dt1
24+
UNION
25+
SELECT a FROM t1 WHERE b IN (SELECT a FROM t1) LIMIT 1)
26+
FROM t1;
27+
--enable_result_log
28+
DROP TABLE t1;

sql/sql_lex.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5071,6 +5071,20 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
50715071
if (empty_union_result)
50725072
subquery_predicate->no_rows_in_result();
50735073

5074+
/*
5075+
If any one SELECT in the subquery has UNCACHEABLE_RAND, then all
5076+
SELECTs should be marked as uncacheable.
5077+
*/
5078+
bool has_rand= false;
5079+
for (SELECT_LEX *sl= un->first_select(); sl && !has_rand;
5080+
sl= sl->next_select())
5081+
has_rand= sl->uncacheable & UNCACHEABLE_RAND;
5082+
if (has_rand)
5083+
{
5084+
for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select())
5085+
sl->uncacheable |= UNCACHEABLE_UNITED;
5086+
}
5087+
50745088
if (is_correlated_unit)
50755089
{
50765090
/*

0 commit comments

Comments
 (0)