Bug#16394084: LOOSE INDEX SCAN WITH QUOTED INT PREDICATE

RETURNS RANDOM DATA
                 
MySQL 5.5 specific version of bugfix.
      
When Loose Index Scan Range access is used, MySQL execution needs
to copy non-aggregated fields. end_send() checked if this was
necessary by checking if join_tab->select->quick had type
QS_TYPE_GROUP_MIN_MAX.
      
In this bug, however, MySQL created a sort index to sort the rows
read from this range access method. create_sort_index() deletes
join_tab->select->quick which makes it impossible to inquire
the join_tab if LIS has been used.
      
The fix for MySQL 5.5 is to introduce a variable in JOIN_TAB
that stores whether or not LIS has been used. There is no need
for this variable in later MySQL versions because the relevant
code has been refactored.
This commit is contained in:
Jorgen Loland 2013-03-20 11:20:12 +01:00
parent 57129a3a4b
commit 015c320a75
2 changed files with 44 additions and 5 deletions

View File

@ -2713,6 +2713,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
s->const_keys.init(); s->const_keys.init();
s->checked_keys.init(); s->checked_keys.init();
s->needed_reg.init(); s->needed_reg.init();
s->filesort_used_loose_index_scan= false;
s->filesort_used_loose_index_scan_agg_distinct= false;
table_vector[i]=s->table=table=tables->table; table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables; table->pos_in_table_list= tables;
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@ -6163,6 +6165,8 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
join_tab->read_first_record= join_init_read_record; join_tab->read_first_record= join_init_read_record;
join_tab->join= this; join_tab->join= this;
join_tab->ref.key_parts= 0; join_tab->ref.key_parts= 0;
join_tab->filesort_used_loose_index_scan= false;
join_tab->filesort_used_loose_index_scan_agg_distinct= false;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
temp_table->status=0; temp_table->status=0;
temp_table->null_row=0; temp_table->null_row=0;
@ -14240,6 +14244,17 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tablesort_result_cache= table->sort.io_cache; tablesort_result_cache= table->sort.io_cache;
table->sort.io_cache= NULL; table->sort.io_cache= NULL;
if (select->quick &&
select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
{
tab->filesort_used_loose_index_scan= true;
QUICK_GROUP_MIN_MAX_SELECT *minmax_quick=
static_cast<QUICK_GROUP_MIN_MAX_SELECT*>(select->quick);
if (minmax_quick->is_agg_distinct())
tab->filesort_used_loose_index_scan_agg_distinct= true;
}
/* /*
If a quick object was created outside of create_sort_index() If a quick object was created outside of create_sort_index()
that might be reused, then do not call select->cleanup() since that might be reused, then do not call select->cleanup() since

View File

@ -243,16 +243,40 @@ typedef struct st_join_table {
nested_join_map embedding_map; nested_join_map embedding_map;
void cleanup(); void cleanup();
/*
In cases where filesort reads rows from a table using Loose Index
Scan, the fact that LIS was used is lost because
create_sort_index() deletes join_tab->select->quick. MySQL needs
this information during JOIN::exec().
This variable is a hack for MySQL 5.5 only. A value of true means
that filesort used LIS to read from the table. In MySQL 5.6 and
later, join_tab->filesort is a separate structure with it's own
select that can be inquired to get the same information. There is
no need for this variable in MySQL 5.6 and later.
*/
bool filesort_used_loose_index_scan;
/*
Similar hack as for filesort_used_loose_index_scan. Not needed for
MySQL 5.6 and later.
*/
bool filesort_used_loose_index_scan_agg_distinct;
inline bool is_using_loose_index_scan() inline bool is_using_loose_index_scan()
{ {
return (select && select->quick && return (filesort_used_loose_index_scan ||
(select->quick->get_type() == (select && select->quick &&
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); (select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
);
} }
bool is_using_agg_loose_index_scan () bool is_using_agg_loose_index_scan ()
{ {
return (is_using_loose_index_scan() && return (filesort_used_loose_index_scan_agg_distinct ||
((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct()); (select && select->quick &&
(select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX) &&
((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct())
);
} }
} JOIN_TAB; } JOIN_TAB;