diff options
author | Sergei Petrunia <sergey@mariadb.com> | 2022-02-10 14:23:20 +0300 |
---|---|---|
committer | Sergei Petrunia <sergey@mariadb.com> | 2022-02-10 20:35:32 +0300 |
commit | 3a52569499e2f0c4d1f25db1e81617a9d9755400 (patch) | |
tree | 4a7641bf1091c29e2f6f5419109620e3bc3046ff /sql/sql_lex.cc | |
parent | 9e2c26b0f6d91b3b6b0deaf9bc82f6e6ebf9a90b (diff) | |
download | mariadb-git-bb-10.2-compatibility.tar.gz |
MDEV-25636: Bug report: abortion in sql/sql_parse.cc:6294mariadb-10.2.43bb-10.2-compatibility
The asserion failure was caused by this query
select /*id=1*/ from t1
where
col= ( select /*id=2*/ from ... where corr_cond1
union
select /*id=4*/ from ... where corr_cond2)
Here,
- select with id=2 was correlated due to corr_cond1.
- select with id=4 was initially correlated due to corr_cond2, but then
the optimizer optimized away the correlation, making the select with id=4
uncorrelated.
However, since select with id=2 remained correlated, the execution had to
re-compute the whole UNION. When it tried to execute select with id=4, it
hit an assertion (join buffer already free'd).
This is because select with id=4 has freed its execution structures after
it has been executed once. The select is uncorrelated, so it did not expect
it would need to be executed for the second time.
Fixed this by adding this logic in
st_select_lex::optimize_unflattened_subqueries():
If a member of a UNION is correlated, mark all its members as
correlated, so that they are prepared to be executed multiple times.
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r-- | sql/sql_lex.cc | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 125bbfe1bfd..47ff2836aba 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3898,7 +3898,21 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only) } if (empty_union_result) subquery_predicate->no_rows_in_result(); - if (!is_correlated_unit) + + if (is_correlated_unit) + { + /* + Some parts of UNION are not correlated. This means we will need to + re-execute the whole UNION every time. Mark all parts of the UNION + as correlated so that they are prepared to be executed multiple + times (if we don't do that, some part of the UNION may free its + execution data at the end of first execution and crash on the second + execution) + */ + for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select()) + sl->uncacheable |= UNCACHEABLE_DEPENDENT; + } + else un->uncacheable&= ~UNCACHEABLE_DEPENDENT; subquery_predicate->is_correlated= is_correlated_unit; } |