Commit 1d791be4 authored by unknown's avatar unknown

Fix for BUG#35273 "Corrupted table if using GIS index":

when modifying R-tree indices we forgot to unpin pages (causing
flush at-end-of-statement to fail - because page is pinned - and thus
mark table corrupted) and also to unlock key_del (causing assertion
failure info->used_key_del==0 at maria_close()).


storage/maria/ma_rt_index.c:
  When modifying pages of R-tree indices we keep them pinned, and
  lock key_del, so we here make sure to unpin and unlock at the end
  of the modification. I checked all functions which add to info->pinned_pages
  or call _ma_lock_key_del(): the parent is always maria_rtree_insert()
  or maria_rtree_delete(), which thus do the unpin/unlock now.
mysql-test/r/maria-gis-rtree.result:
  new result, which is incorrect (filed as BUG#35351) but at least
  test does not crash anymore
mysql-test/t/maria-gis-rtree.test:
  test of Maria's GIS functionality (R-tree indices etc); copied from
  MyISAM's gis-rtree.test; used to crash without the bugfixes.
parent 61788ff4
This diff is collapsed.
This diff is collapsed.
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "maria_def.h" #include "maria_def.h"
#include "trnman.h"
#include "ma_key_recover.h"
#ifdef HAVE_RTREE_KEYS #ifdef HAVE_RTREE_KEYS
...@@ -762,10 +764,14 @@ err1: ...@@ -762,10 +764,14 @@ err1:
int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length) int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
{ {
int res;
DBUG_ENTER("maria_rtree_insert"); DBUG_ENTER("maria_rtree_insert");
DBUG_RETURN((!key_length || res= - (!key_length ||
(maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ? (maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1));
-1 : 0); _ma_fast_unlock_key_del(info);
/** @todo RECOVERY use a real LSN */
_ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE);
DBUG_RETURN(res);
} }
...@@ -980,6 +986,7 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ...@@ -980,6 +986,7 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
my_off_t old_root; my_off_t old_root;
MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr; MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr;
MARIA_PINNED_PAGE *page_link, *root_page_link; MARIA_PINNED_PAGE *page_link, *root_page_link;
int res;
DBUG_ENTER("maria_rtree_delete"); DBUG_ENTER("maria_rtree_delete");
if ((old_root= share->state.key_root[keynr]) == HA_OFFSET_ERROR) if ((old_root= share->state.key_root[keynr]) == HA_OFFSET_ERROR)
...@@ -999,7 +1006,8 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ...@@ -999,7 +1006,8 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
case 2: /* empty */ case 2: /* empty */
{ {
share->state.key_root[keynr]= HA_OFFSET_ERROR; share->state.key_root[keynr]= HA_OFFSET_ERROR;
DBUG_RETURN(0); res= 0;
goto err;
} }
case 0: /* deleted */ case 0: /* deleted */
{ {
...@@ -1028,7 +1036,6 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ...@@ -1028,7 +1036,6 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
last= rt_PAGE_END(share, page_buf); last= rt_PAGE_END(share, page_buf);
for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_length, nod_flag)) for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_length, nod_flag))
{ {
int res;
if ((res= if ((res=
maria_rtree_insert_level(info, keynr, k, key_length, maria_rtree_insert_level(info, keynr, k, key_length,
ReinsertList.pages[i].level)) == -1) ReinsertList.pages[i].level)) == -1)
...@@ -1049,6 +1056,7 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ...@@ -1049,6 +1056,7 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
} }
} }
} }
res= 0;
my_afree(page_buf); my_afree(page_buf);
page_link->changed= 1; page_link->changed= 1;
if (_ma_dispose(info, ReinsertList.pages[i].offs, 0)) if (_ma_dispose(info, ReinsertList.pages[i].offs, 0))
...@@ -1078,20 +1086,29 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length) ...@@ -1078,20 +1086,29 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
share->state.key_root[keynr]= new_root; share->state.key_root[keynr]= new_root;
} }
info->update= HA_STATE_DELETED; info->update= HA_STATE_DELETED;
DBUG_RETURN(0); res= 0;
goto err;
err1: err1:
DBUG_RETURN(-1); /* purecov: inspected */ res= -1;
goto err; /* purecov: inspected */
} }
case 1: /* not found */ case 1: /* not found */
{ {
my_errno= HA_ERR_KEY_NOT_FOUND; my_errno= HA_ERR_KEY_NOT_FOUND;
DBUG_RETURN(-1); /* purecov: inspected */ res= -1;
goto err; /* purecov: inspected */
} }
default: default:
case -1: /* error */ case -1: /* error */
DBUG_RETURN(-1); /* purecov: inspected */ res= -1;
goto err; /* purecov: inspected */
} }
err:
_ma_fast_unlock_key_del(info);
/** @todo RECOVERY use a real LSN */
_ma_unpin_all_pages_and_finalize_row(info, LSN_IMPOSSIBLE);
DBUG_RETURN(res);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment