Skip to content

Commit 38cbef8

Browse files
committed
MDEV-22935 Erroneous Aria Index / Optimizer behaviour
The problem was in the Aria part of the range optimizer, maria_records_in_range(), which wrong concluded that there was no rows in the range. This error would happen in the unlikely case when searching for a range on a partial key and there was a match for the first key part in the upper part of the b-tree (node) and also a match in the underlying node page. In other words, for this bug to happen one have to use Aria, have a multi part key with a lot of identical values for the first key part and do a range search on the second part of the key. Fixed by ensuring that we do not stop searching for partial keys found on node. Other things: - Added some comments - Changed a variable name to more clearly explain it's purpose. - Fixed wrong cast in _ma_record_pos() that could cause problems on 32 bit systems.
1 parent c6d36c3 commit 38cbef8

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

mysql-test/suite/maria/range.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#
2+
# MDEV-22935 Erroneous Aria Index / Optimizer behaviour
3+
#
4+
create table t1 (a char(255), b datetime, primary key(a,b)) engine=aria transactional=0 pack_keys=0;
5+
insert into t1 select concat("hello world hello world", truncate(seq/100,0)),from_unixtime(seq+1) from seq_1_to_20000;
6+
drop table t1;

mysql-test/suite/maria/range.test

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--source include/have_sequence.inc
2+
3+
--echo #
4+
--echo # MDEV-22935 Erroneous Aria Index / Optimizer behaviour
5+
--echo #
6+
7+
create table t1 (a char(255), b datetime, primary key(a,b)) engine=aria transactional=0 pack_keys=0;
8+
insert into t1 select concat("hello world hello world", truncate(seq/100,0)),from_unixtime(seq+1) from seq_1_to_20000;
9+
10+
let $i= 200;
11+
--disable_query_log
12+
while ($i)
13+
{
14+
let $tmp= `select count(*) from t1 where a="hello world hello world$i" and b <= from_unixtime($i*100+1)`;
15+
if (`SELECT $tmp != 1`)
16+
{
17+
--echo "Found $tmp rows, expected 1, for value $i"
18+
}
19+
dec $i;
20+
}
21+
--enable_query_log
22+
drop table t1;

storage/maria/ma_range.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key_data,
191191
info->s->state.key_root[inx], final_page);
192192
if (pos >= 0.0)
193193
{
194-
DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records)));
195-
DBUG_RETURN((ulong) (pos*info->state->records+0.5));
194+
DBUG_PRINT("exit",("pos: %lld",(longlong) (pos*info->state->records)));
195+
DBUG_RETURN((ha_rows) (pos*info->state->records+0.5));
196196
}
197197
DBUG_RETURN(HA_POS_ERROR);
198198
}
@@ -214,7 +214,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
214214
{
215215
int flag;
216216
uint keynr, UNINIT_VAR(max_keynr);
217-
my_bool after_key;
217+
my_bool last_key_on_page;
218218
uchar *keypos;
219219
double offset;
220220
MARIA_KEYDEF *keyinfo= key->keyinfo;
@@ -230,7 +230,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
230230
goto err;
231231
*final_page= pos;
232232
flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos,
233-
info->lastkey_buff, &after_key);
233+
info->lastkey_buff, &last_key_on_page);
234234
keynr= _ma_keynr(&page, keypos, &max_keynr);
235235

236236
if (flag)
@@ -274,7 +274,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
274274
There may be identical keys in the tree. Try to match on of those.
275275
Matches keynr + [0-1]
276276
*/
277-
if ((offset= _ma_search_pos(info, key, SEARCH_FIND,
277+
if ((offset= _ma_search_pos(info, key, nextflag,
278278
_ma_kpos(page.node,keypos),
279279
final_page)) < 0)
280280
DBUG_RETURN(offset); /* Read error */
@@ -290,9 +290,10 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
290290

291291

292292
/*
293-
Get keynummer of current key and max number of keys in nod
293+
Get keynumber of current key and max number of keys in nod
294294
295-
keynr >= 0 && key_nr <= max_key
295+
@return key position on page (0 - (ret_max_key - 1))
296+
ret_max_key contains how many keys there was on the page
296297
*/
297298

298299
static uint _ma_keynr(MARIA_PAGE *page, uchar *keypos, uint *ret_max_key)

0 commit comments

Comments
 (0)