The crash happens for the following reason.
The function Item_subselect::fix_fields contains the loop:
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
that is supposed to look trough all union operands at the top level of the processed IN/ALL/ANY subquery and wrap each table value constructor into a select:
<values ...> => select * from (<value...>) t
This transformation allows us to use all optimizations applied to multi-select IN subqueries.
Apparently this transformation changes the selects of the union. If a TVC is transformed then it is substituted for a <wrapping select> in the union chain. To get the next element in the chain we should have used
<wrapping select> ->next_select() instead of sl ->next_select() that returns 0. As a result the loop ends prematurely and any TVC following the first one in the chain is not wrapped into select.
For the reported test case we have after the above loop:
select a from t1 where a in (select * from (values (7)) tvc_0 union values (8));
Such queries are not expected by the optimizer phase and cause crashes.
Igor Babaev (Inactive)
added a comment - The crash happens for the following reason.
The function Item_subselect::fix_fields contains the loop:
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
that is supposed to look trough all union operands at the top level of the processed IN/ALL/ANY subquery and wrap each table value constructor into a select:
<values ...> => select * from (<value...>) t
This transformation allows us to use all optimizations applied to multi-select IN subqueries.
Apparently this transformation changes the selects of the union. If a TVC is transformed then it is substituted for a <wrapping select> in the union chain. To get the next element in the chain we should have used
<wrapping select> ->next_select() instead of sl ->next_select() that returns 0. As a result the loop ends prematurely and any TVC following the first one in the chain is not wrapped into select.
For the reported test case we have after the above loop:
select a from t1 where a in (select * from (values (7)) tvc_0 union values (8));
Such queries are not expected by the optimizer phase and cause crashes.
The easiest solution for the problem is to use the loop
SELECT_LEX *next_sl= 0;
for (SELECT_LEX *sl= unit->first_select(); sl; sl= next_sl)
{
next_sl= sl->next_select();
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
Yet I prefer to return the new wrapping select by the function Item_subselect::wrap_tvc_into_select in the case of success. In the case of failure the function will return 0;
Igor Babaev (Inactive)
added a comment - The easiest solution for the problem is to use the loop
SELECT_LEX *next_sl= 0;
for (SELECT_LEX *sl= unit->first_select(); sl; sl= next_sl)
{
next_sl= sl->next_select();
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
Yet I prefer to return the new wrapping select by the function Item_subselect::wrap_tvc_into_select in the case of success. In the case of failure the function will return 0;
The crash happens for the following reason.
The function Item_subselect::fix_fields contains the loop:
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
if (sl->tvc)
{
wrap_tvc_into_select(thd, sl);
}
}
that is supposed to look trough all union operands at the top level of the processed IN/ALL/ANY subquery and wrap each table value constructor into a select:
<values ...> => select * from (<value...>) t
This transformation allows us to use all optimizations applied to multi-select IN subqueries.
Apparently this transformation changes the selects of the union. If a TVC is transformed then it is substituted for a <wrapping select> in the union chain. To get the next element in the chain we should have used
<wrapping select> ->next_select() instead of sl ->next_select() that returns 0. As a result the loop ends prematurely and any TVC following the first one in the chain is not wrapped into select.
For the reported test case we have after the above loop:
select a from t1 where a in (select * from (values (7)) tvc_0 union values (8));
Such queries are not expected by the optimizer phase and cause crashes.