This bug manifests itself for INSERT...SELECT statements whose WHERE condition contained an IN/ANY/ALL predicand with such grouping subquery that:
its GROUP BY clause can be eliminated,
the GROUP clause contains a subquery over a mergeable derived table referencing the updated table.
Here's an example of such INSERT...SELECT statement:
insertinto t1
select b from t2
where b in (select c from t3
groupby (select * from (select a from t1) dt where a = 1));
Execution of this query causes a crash of the server at the prepare phase.
The bug causes similar crash when executing a single-table DELETE statement if it uses a WHERE condition with EXISTS subquery whose WHERE condition is such as described above for affected INSERT...SELECT statements. Here's an example of such DELETE statement
deletefrom t1
where exists (select b from t2
where b in (select c from t3
groupby (select * from (select a from t1) dt where a = 1)));
Igor Babaev (Inactive)
added a comment - - edited This bug manifests itself for INSERT...SELECT statements whose WHERE condition contained an IN/ANY/ALL predicand with such grouping subquery that:
its GROUP BY clause can be eliminated,
the GROUP clause contains a subquery over a mergeable derived table referencing the updated table.
Here's an example of such INSERT...SELECT statement:
insert into t1
select b from t2
where b in ( select c from t3
group by ( select * from ( select a from t1) dt where a = 1));
Execution of this query causes a crash of the server at the prepare phase.
The bug causes similar crash when executing a single-table DELETE statement if it uses a WHERE condition with EXISTS subquery whose WHERE condition is such as described above for affected INSERT...SELECT statements. Here's an example of such DELETE statement
delete from t1
where exists ( select b from t2
where b in ( select c from t3
group by ( select * from ( select a from t1) dt where a = 1)));
When executing the INSERT...SELECT statement from the previous comment we come to the call of JOIN::prepare() for the subquery of the IN predicand. JOIN::prepare notices that the GROUP BY clause of the subquery can be e liminated and it calls remove_redundant_subquery_clauses() that removes the subquery of the GROUP BY clause. The corresponding select together with underlying select of the derived table are excluded from the select tree of the statement. The call of select_insert::prepare() checks whether any of the tables used the SELECT part of the statement is the same as the updated table by invoking unique_table() and then find_dup_table() inside it. find_dup_table() sees that this is the case for table t1 used in the derived table and it forces the materialization of the derived table dt calling TABLE_LIST::set_materialized_derived() in spite of the fact that the
select specifying this derived table was excluded from the tree. TABLE_LIST::set_check_materialized() is called dt. At this moment we discover that unit specifying dt has not been marked as excluded and the first attempt to get its first select causes a crash.
Igor Babaev (Inactive)
added a comment - When executing the INSERT...SELECT statement from the previous comment we come to the call of JOIN::prepare() for the subquery of the IN predicand. JOIN::prepare notices that the GROUP BY clause of the subquery can be e liminated and it calls remove_redundant_subquery_clauses() that removes the subquery of the GROUP BY clause. The corresponding select together with underlying select of the derived table are excluded from the select tree of the statement. The call of select_insert::prepare() checks whether any of the tables used the SELECT part of the statement is the same as the updated table by invoking unique_table() and then find_dup_table() inside it. find_dup_table() sees that this is the case for table t1 used in the derived table and it forces the materialization of the derived table dt calling TABLE_LIST::set_materialized_derived() in spite of the fact that the
select specifying this derived table was excluded from the tree. TABLE_LIST::set_check_materialized() is called dt. At this moment we discover that unit specifying dt has not been marked as excluded and the first attempt to get its first select causes a crash.
Confirmed on 10.3.35+c9b5a05341d7342db5f369493ea200b5fb9db243 for the first insert statement. Following SQL not needed.