Fix LP BUG#680943

Analysis:
The problem lies in filesort.cc:find_all_keys().

When find_all_keys() is called for the outer query, it resets all
of the tree sets of fields - [read,write,vcol]_set and recomputes
them with respect to sorting.

However, in the loop for each current record the procedure calls
select->skip_record(thd), which evaluates the where clause, which
in turns evaluates the subquery. The JOIN evaluation of the
subquery eventually calls Field_long::val_int to evaluate the field
alias1.f1. The assertion condition
  "bitmap_is_set(table->read_set, field_index)"
fails, because the outer query changed the read_set of table "alias1".

Solution:
Restore the original read_set of the table before calling
SQL_SELECT::skip_record, then revert back to the read_set used in
find_all_keys.
This commit is contained in:
unknown 2010-12-02 14:39:37 +02:00
commit 1b3336dc30
3 changed files with 65 additions and 5 deletions

View file

@ -613,10 +613,34 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
}
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
}
bool write_record= false;
if (error == 0)
{
param->examined_rows++;
if (error == 0 && (!select || select->skip_record(thd) > 0))
if (select && select->cond)
{
/*
If the condition 'select->cond' contains a subquery, restore the
original read/write sets of the table 'sort_form' because when
SQL_SELECT::skip_record evaluates this condition. it may include a
correlated subquery predicate, such that some field in the subquery
refers to 'sort_form'.
*/
if (select->cond->with_subselect)
sort_form->column_bitmaps_set(save_read_set, save_write_set,
save_vcol_set);
write_record= (select->skip_record(thd) > 0);
if (select->cond->with_subselect)
sort_form->column_bitmaps_set(&sort_form->tmp_set,
&sort_form->tmp_set,
&sort_form->tmp_set);
}
else
write_record= true;
}
if (write_record)
{
if (idx == param->keys)
{
@ -629,7 +653,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
}
else
file->unlock_row();
/* It does not make sense to read more keys in case of a fatal error */
if (thd->is_error())
break;