Commit 6f8b60c1 authored by Monty's avatar Monty Committed by Sergei Golubchik

Indexes where not used for sorting in sub queries

This happens when the subquery marks some index fields as constant
but the fields are still present in GROUP BY

Fixed by checking if the 'constant field' is still part of GROUP BY before
skipping it.

Other things:
- Added Item_field::contains() to make it easier to check if a field
  is equal to a Item_field or part of Item_equal.
parent 9f7f597e
......@@ -146,7 +146,7 @@ EXPLAIN
SELECT *
FROM
t1 JOIN
(SELECT t1.a, t1.b FROM t1, t2 WHERE t1.b = t2.c GROUP BY t1.a, t1.b) as dt
(SELECT t1_inner.a, t1_inner.b FROM t1 as t1_inner, t2 as t2_inner WHERE t1_inner.b = t2_inner.c GROUP BY t1_inner.a, t1_inner.b) as dt
WHERE
t1.a = dt.a;
......
......@@ -6342,6 +6342,24 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
}
/*
Check if field is is equal to current field or any of the fields in
item_equal
*/
bool Item_field::contains(Field *field_arg)
{
if (field == field_arg)
return 1;
/*
Check if there is a multiple equality that allows to infer that field
(see also: compute_part_of_sort_key_for_equals)
*/
if (item_equal && item_equal->contains(field_arg))
return 1;
return 0;
}
/**
Set a pointer to the multiple equality the field reference belongs to
(if any).
......
......@@ -3780,6 +3780,7 @@ class Item_field :public Item_ident,
Item_equal *get_item_equal() override { return item_equal; }
void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal) override;
bool contains(Field *field);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override;
Item *replace_equal_field(THD *thd, uchar *arg) override;
uint32 max_display_length() const override
......
......@@ -24851,6 +24851,7 @@ static int test_if_order_by_key(JOIN *join,
uint key_parts;
bool have_pk_suffix= false;
uint pk= table->s->primary_key;
ORDER::enum_order keypart_order;
DBUG_ENTER("test_if_order_by_key");
if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
......@@ -24863,16 +24864,23 @@ static int test_if_order_by_key(JOIN *join,
for (; order ; order=order->next, const_key_parts>>=1)
{
Item_field *item_field= ((Item_field*) (*order->item)->real_item());
Field *field= item_field->field;
int flag;
/*
Skip key parts that are constants in the WHERE clause.
These are already skipped in the ORDER BY by const_expression_in_where()
for top level queries.
*/
for (; const_key_parts & 1 ; const_key_parts>>= 1)
key_part++;
{
if (item_field->contains(key_part->field))
{
/* Subquery with ORDER BY, continue with next field */
goto next_order_field;
}
key_part++;
}
/*
This check was in this function historically (although I think it's
better to check it outside of this function):
......@@ -24897,36 +24905,27 @@ static int test_if_order_by_key(JOIN *join,
goto ok;
}
if (key_part == key_part_end)
if (key_part == key_part_end ||
!key_part->field->part_of_sortkey.is_set(idx))
{
/*
There are some items left in ORDER BY that we don't
There are some items left in ORDER BY that we don't have in the key
*/
DBUG_RETURN(0);
}
if (key_part->field != field)
{
/*
Check if there is a multiple equality that allows to infer that field
and key_part->field are equal
(see also: compute_part_of_sort_key_for_equals)
*/
if (item_field->item_equal &&
item_field->item_equal->contains(key_part->field))
field= key_part->field;
}
if (key_part->field != field || !field->part_of_sortkey.is_set(idx))
if (!item_field->contains(key_part->field))
DBUG_RETURN(0);
const ORDER::enum_order keypart_order=
(key_part->key_part_flag & HA_REVERSE_SORT) ?
ORDER::ORDER_DESC : ORDER::ORDER_ASC;
keypart_order= ((key_part->key_part_flag & HA_REVERSE_SORT) ?
ORDER::ORDER_DESC : ORDER::ORDER_ASC);
/* set flag to 1 if we can use read-next on key, else to -1 */
flag= (order->direction == keypart_order) ? 1 : -1;
if (reverse && flag != reverse)
DBUG_RETURN(0);
reverse=flag; // Remember if reverse
next_order_field:
if (key_part < key_part_end)
key_part++;
}
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