mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fix for bug MDEV-3992
Analysis:
The crash is a result of incorrect analysis of whether a secondary key
can be extended with a primary in order to compute ORDER BY. The analysis
is done in test_if_order_by_key(). This function doesn't take into account
that the primary key may in fact index the same columns as the secondary
key. For the test query test_if_order_by_key says that there is an extended
key with total 2 keyparts.
At the same time, the condition
if (pkinfo->key_part[i].field->key_start.is_set(nr))
in test_if_cheaper_oredring() becomes true for (i == 0), which results in
an invalid access to rec_per_key[-1].
Solution:
The best solution would be to reuse KEY::ext_key_parts that is already computed
by open_binary_frm(), however after detailed analysis the conclusion is that
the change would be too intrusive for a GA release.
The solution for 5.5 is to add a guard for the case when the 0-th key part is
considered, and to assume that all keys will be scanned in this case.
This commit is contained in:
@@ -18144,7 +18144,15 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
|
||||
key_part_end=key_part+table->key_info[table->s->primary_key].key_parts;
|
||||
const_key_parts=table->const_key_parts[table->s->primary_key];
|
||||
|
||||
for (; const_key_parts & 1 ; const_key_parts>>= 1)
|
||||
/*
|
||||
Check for constness only those keyparts of the PK suffix, that will
|
||||
be used to extend the secondary key 'idx'. This handles the case when
|
||||
some columns of the PK are used in the secondary index.
|
||||
*/
|
||||
for (uint pk_part_idx= 0;
|
||||
((const_key_parts & 1) &&
|
||||
(table->key_info[idx].ext_key_part_map & (1 << pk_part_idx)));
|
||||
const_key_parts>>= 1, pk_part_idx++)
|
||||
key_part++;
|
||||
/*
|
||||
The primary and secondary key parts were all const (i.e. there's
|
||||
@@ -23009,7 +23017,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
|
||||
if rec_per_key[0] != 0.
|
||||
*/
|
||||
DBUG_ASSERT(pkinfo->rec_per_key[i]);
|
||||
rec_per_key*= pkinfo->rec_per_key[i-1];
|
||||
rec_per_key*= (i == 0) ? table_records :
|
||||
pkinfo->rec_per_key[i-1];
|
||||
rec_per_key/= pkinfo->rec_per_key[i];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user