1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fix for BUG#35351 "Maria: R-tree index does not return all expected rows"

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.
This commit is contained in:
unknown
2008-04-11 11:53:21 +02:00
parent b765997467
commit 28131daa26
3 changed files with 27 additions and 11 deletions

View File

@ -8,7 +8,7 @@ else
COMMITTER=$USER
fi
FROM=$COMMITTER@mysql.com
COMMITS=commits@lists.mysql.com
COMMITS=maria@lists.mysql.com
DOCS=docs-commit@mysql.com
LIMIT=10000
VERSION="maria"
@ -73,11 +73,11 @@ else
fi
#++
# commits@ or dev-private@ mail
# maria@ or dev-private@ mail
#--
LIST="commits"
TO="commits@lists.mysql.com"
TO="maria@lists.mysql.com"
if [ -f .tree-is-private ]
then
LIST="dev-private"