mirror of
https://github.com/MariaDB/server.git
synced 2025-11-24 06:01:25 +03:00
BitKeeper/triggers/post-commit:
commits to Maria public list
mysql-test/r/maria-gis-rtree.result:
result is good now, similar to MyISAM's (gis-rtree.result)
storage/maria/ma_rt_index.c:
R-tree key-reading code used info->buff as a cache for the next key read,
but between key read and next key read, there is record read, which
uses info->buff too. In detail, during a SELECT:
First key read: maria_rfirst() is called, which calls maria_rtree_find_first() which calls
maria_rtree_find_req() which comes here
if (after_key < last)
{
// ! the list of keys is copied to info->buff
// and info->buff is remembered in info->int_keypos
info->int_keypos= info->buff;
info->int_maxpos= info->buff + (last - after_key);
memcpy(info->buff, after_key, last - after_key);
info->keyread_buff_used= 0;
}
Then record read:
_ma_read_block_record() (as well as some other functions of
ma_blockrec.c) overwrites info->buff:
if (!(buff= pagecache_read(share->pagecache,
&info->dfile, ma_recordpos_to_page(record_pos), 0,
info->buff, share->page_type,
PAGECACHE_LOCK_LEFT_UNLOCKED, 0)))
So, this has the effect that the keys saved by maria_rtree_find_req() are now lost:
info->int_keypos now contains a copy of a data page!
Then maria_rnext_same() runs (to find second row), calls maria_rtree_find_next() which
does:
if (!info->keyread_buff_used)
{
uchar *key= info->int_keypos;
while (key < info->int_maxpos)
{
if (!maria_rtree_key_cmp(keyinfo->seg,
info->first_mbr_key, key,
info->last_rkey_length, search_flag))
i.e. maria_rtree_key_cmp() is doing comparisons on values it reads from the data page.
Naturally this is bad and no row is found.
Origin of the bug: MARIA_HA::keyread_buff is new in Maria.
Solution: use keyread_buff instead of buff (like _ma_search_next() does),
in R-tree code. Note that ma_blockrec.c functions also use keyread_buff
but they all are write-functions, which should not be running close
to next-key-read. Also note that some ma_rt_index.c functions still
use info->buff, but they are about writes too.
Thanks Monty for the idea.
2.9 KiB
Executable File
2.9 KiB
Executable File