diff --git a/sql/filesort.cc b/sql/filesort.cc index c2ea2647351..ae51fb94e64 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -137,7 +137,8 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, */ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, - Filesort_tracker* tracker) + Filesort_tracker* tracker, JOIN *join, + table_map first_table_bit) { int error; size_t memory_available= thd->variables.sortbuff_size; @@ -154,7 +155,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, DBUG_ENTER("filesort"); - if (!(s_length= filesort->make_sortorder(thd))) + if (!(s_length= filesort->make_sortorder(thd, join, first_table_bit))) DBUG_RETURN(NULL); /* purecov: inspected */ DBUG_EXECUTE("info",TEST_filesort(filesort->sortorder,s_length);); @@ -438,7 +439,7 @@ void Filesort::cleanup() } -uint Filesort::make_sortorder(THD *thd) +uint Filesort::make_sortorder(THD *thd, JOIN *join, table_map first_table_bit) { uint count; SORT_FIELD *sort,*pos; @@ -458,7 +459,30 @@ uint Filesort::make_sortorder(THD *thd) for (ord= order; ord; ord= ord->next, pos++) { - Item *item= ord->item[0]->real_item(); + Item *first= ord->item[0]; + /* + It is possible that the query plan is to read table t1, while the + sort criteria actually has "ORDER BY t2.col" and the WHERE clause has + a multi-equality(t1.col, t2.col, ...). + The optimizer detects such cases (grep for + UseMultipleEqualitiesToRemoveTempTable to see where), but doesn't + perform equality substitution in the order->item. We need to do the + substitution here ourselves. + */ + table_map item_map= first->used_tables(); + if (join && (item_map & ~join->const_table_map) && + !(item_map & first_table_bit) && join->cond_equal && + first->get_item_equal()) + { + /* + Ok, this is the case descibed just above. Get the first element of the + multi-equality. + */ + Item_equal *item_eq= first->get_item_equal(); + first= item_eq->get_first(NO_PARTICULAR_TAB, NULL); + } + + Item *item= first->real_item(); pos->field= 0; pos->item= 0; if (item->type() == Item::FIELD_ITEM) pos->field= ((Item_field*) item)->field; @@ -474,7 +498,7 @@ uint Filesort::make_sortorder(THD *thd) DBUG_ASSERT(pos->field != NULL || pos->item != NULL); } DBUG_RETURN(count); - } +} /** Read 'count' number of buffer pointers into memory. */ diff --git a/sql/filesort.h b/sql/filesort.h index 18029a10c14..2b4f7ac2654 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -26,6 +26,7 @@ struct TABLE; class Filesort_tracker; struct SORT_FIELD; typedef struct st_order ORDER; +class JOIN; /** @@ -72,7 +73,7 @@ public: ~Filesort() { cleanup(); } /* Prepare ORDER BY list for sorting. */ - uint make_sortorder(THD *thd); + uint make_sortorder(THD *thd, JOIN *join, table_map first_table_bit); private: void cleanup(); @@ -152,11 +153,13 @@ public: { return filesort_buffer.sort_buffer_size(); } friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, - Filesort_tracker* tracker); + Filesort_tracker* tracker, JOIN *join, + table_map first_table_bit); }; SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, - Filesort_tracker* tracker); + Filesort_tracker* tracker, JOIN *join=NULL, + table_map first_table_bit=0); void change_double_for_sort(double nr,uchar *to); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cde2cc43b0f..5cc7798fde9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -21427,7 +21427,7 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) if (table->s->tmp_table) table->file->info(HA_STATUS_VARIABLE); // Get record count - file_sort= filesort(thd, table, fsort, fsort->tracker); + file_sort= filesort(thd, table, fsort, fsort->tracker, join, tab->table->map); DBUG_ASSERT(tab->filesort_result == 0); tab->filesort_result= file_sort; tab->records= 0;