diff options
author | Michael Widenius <monty@askmonty.org> | 2013-02-28 10:00:07 +0100 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2013-02-28 10:00:07 +0100 |
commit | 6a2d730a7f89726f30dc2eb3a02a9aaa94da6c3c (patch) | |
tree | c30c547229e6ef879528404109c9cba97abe16c4 /storage/heap/hp_delete.c | |
parent | 08ba257846e75641304e530b7a4a4ab21b1714d7 (diff) | |
download | mariadb-git-6a2d730a7f89726f30dc2eb3a02a9aaa94da6c3c.tar.gz |
Fixed BUG#51763 Can't delete rows from MEMORY table with HASH key
Diffstat (limited to 'storage/heap/hp_delete.c')
-rw-r--r-- | storage/heap/hp_delete.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index 455996e32ef..7612b896ccc 100644 --- a/storage/heap/hp_delete.c +++ b/storage/heap/hp_delete.c @@ -47,7 +47,6 @@ int heap_delete(HP_INFO *info, const uchar *record) share->del_link=pos; pos[share->reclength]=0; /* Record deleted */ share->deleted++; - info->current_hash_ptr=0; #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) DBUG_EXECUTE("check_heap",heap_check_heap(info, 0);); #endif @@ -180,21 +179,50 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, } pos2= hp_mask(lastpos_hashnr, blength, share->records + 1); if (pos2 == hp_mask(pos_hashnr, blength, share->records + 1)) - { /* Identical key-positions */ + { + /* lastpos and the row in the main bucket entry (pos) has the same hash */ if (pos2 != share->records) { - empty[0]=lastpos[0]; + /* + The bucket entry was not deleted. Copy lastpos over the + deleted entry and update previous link to point to it. + */ + empty[0]= lastpos[0]; hp_movelink(lastpos, pos, empty); + if (last_ptr == lastpos) + { + /* + We moved the row that info->current_hash_ptr points to. + Update info->current_hash_ptr to point to the new position. + */ + info->current_hash_ptr= empty; + } DBUG_RETURN(0); } - pos3= pos; /* Link pos->next after lastpos */ - } - else - { - pos3= 0; /* Different positions merge */ - keyinfo->hash_buckets--; + /* + Shrinking the hash table deleted the main bucket entry for this hash. + In this case the last entry was the first key in the key chain. + We move things around so that we keep the original key order to ensure + that heap_rnext() works. + + - Move the row at the main bucket entry to the empty spot. + - Move the last entry first in the new chain. + - Link in the first element of the hash. + */ + empty[0]= pos[0]; + pos[0]= lastpos[0]; + hp_movelink(pos, pos, empty); + + /* Update current_hash_ptr if the entry moved */ + if (last_ptr == lastpos) + info->current_hash_ptr= pos; + else if (last_ptr == pos) + info->current_hash_ptr= empty; + DBUG_RETURN(0); } + pos3= 0; /* Different positions merge */ + keyinfo->hash_buckets--; empty[0]=lastpos[0]; hp_movelink(pos3, empty, pos->next_key); pos->next_key=empty; |