Commit ffac8548 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-8989 ORDER BY optimizer ignores equality propagation

Restore the fix from the commit 99cd5a96 that was lost in a merge.
parent 76f492e2
......@@ -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. */
......
......@@ -26,6 +26,7 @@ struct TABLE;
class Filesort_tracker;
struct SORT_FIELD;
typedef struct st_order ORDER;
class JOIN;
/**
......@@ -72,7 +73,7 @@ class Filesort: public Sql_alloc
~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 @@ class SORT_INFO
{ 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);
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment