summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJorgen Loland <jorgen.loland@oracle.com>2013-03-20 11:20:12 +0100
committerJorgen Loland <jorgen.loland@oracle.com>2013-03-20 11:20:12 +0100
commit30e2a543872915353b9d4b1e45e51c8d793965bf (patch)
tree918c03c33a30b6b821be3023a582cc4334147561
parent3d10d7d12414efa077d0721bc8a6166d420b8110 (diff)
downloadmariadb-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.cc15
-rw-r--r--sql/sql_select.h34
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;