1
0
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:
unknown
2013-01-14 15:05:05 +02:00
parent edc89f7511
commit cf79c01cc7
3 changed files with 79 additions and 2 deletions

View File

@@ -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];
}
}