diff options
author | Jorgen Loland <jorgen.loland@oracle.com> | 2013-03-20 11:20:12 +0100 |
---|---|---|
committer | Jorgen Loland <jorgen.loland@oracle.com> | 2013-03-20 11:20:12 +0100 |
commit | 30e2a543872915353b9d4b1e45e51c8d793965bf (patch) | |
tree | 918c03c33a30b6b821be3023a582cc4334147561 | |
parent | 3d10d7d12414efa077d0721bc8a6166d420b8110 (diff) | |
download | mariadb-git-30e2a543872915353b9d4b1e45e51c8d793965bf.tar.gz |
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.
-rw-r--r-- | sql/sql_select.cc | 15 | ||||
-rw-r--r-- | sql/sql_select.h | 34 |
2 files changed, 44 insertions, 5 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d40c7cb7c81..2f20d7aad17 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2713,6 +2713,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, s->const_keys.init(); s->checked_keys.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->pos_in_table_list= tables; 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->join= this; 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)); temp_table->status=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; 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() that might be reused, then do not call select->cleanup() since diff --git a/sql/sql_select.h b/sql/sql_select.h index 6732eb354d6..fc39eb30984 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -243,16 +243,40 @@ typedef struct st_join_table { nested_join_map embedding_map; 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() { - return (select && select->quick && - (select->quick->get_type() == - QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); + return (filesort_used_loose_index_scan || + (select && select->quick && + (select->quick->get_type() == + QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) + ); } bool is_using_agg_loose_index_scan () { - return (is_using_loose_index_scan() && - ((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct()); + return (filesort_used_loose_index_scan_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; |