Commit 7042dd38 authored by Michael Widenius's avatar Michael Widenius

Fixed BUG#51763 Can't delete rows from MEMORY table with HASH key

mysql-test/suite/heap/heap.result:
  Added test case
mysql-test/suite/heap/heap.test:
  Added test case
storage/heap/hp_delete.c:
  Fixed that we don't change order of keys for the current key when we delete them from the hash table.
  Fixed that 'current_hash_ptr' is correct after heap_delete_key().
  Don't "reset current_hash_ptr" on delete; This will improve time a lot for delete of rows when not all rows matches the search criteria.
parent a555ceb2
......@@ -790,3 +790,22 @@ select data_length,index_length from information_schema.tables where table_schem
data_length index_length
81024 121024
drop table t1;
CREATE TABLE t1 (
id int(11) NOT NULL AUTO_INCREMENT,
color enum('GREEN', 'WHITE') DEFAULT NULL,
ts int,
PRIMARY KEY (id),
KEY color (color) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES("1","GREEN",1);
INSERT INTO t1 VALUES("2","GREEN",1);
INSERT INTO t1 VALUES("3","GREEN",1);
INSERT INTO t1 VALUES("4","GREEN",1);
INSERT INTO t1 VALUES("5","GREEN",1);
INSERT INTO t1 VALUES("6","GREEN",1);
DELETE FROM t1 WHERE id = 1;
INSERT INTO t1 VALUES("7","GREEN", 2);
DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN';
SELECT * from t1 WHERE ts = 1 AND color = 'GREEN';
id color ts
DROP TABLE t1;
......@@ -537,3 +537,27 @@ insert into t1 select rand(100000000) from t1;
--replace_result 40512 81024 60512 121024
select data_length,index_length from information_schema.tables where table_schema="test" and table_name="t1";
drop table t1;
#
# BUG#51763 Can't delete rows from MEMORY table with HASH key
#
CREATE TABLE t1 (
id int(11) NOT NULL AUTO_INCREMENT,
color enum('GREEN', 'WHITE') DEFAULT NULL,
ts int,
PRIMARY KEY (id),
KEY color (color) USING HASH
) ENGINE=MEMORY DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES("1","GREEN",1);
INSERT INTO t1 VALUES("2","GREEN",1);
INSERT INTO t1 VALUES("3","GREEN",1);
INSERT INTO t1 VALUES("4","GREEN",1);
INSERT INTO t1 VALUES("5","GREEN",1);
INSERT INTO t1 VALUES("6","GREEN",1);
DELETE FROM t1 WHERE id = 1;
INSERT INTO t1 VALUES("7","GREEN", 2);
DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN';
SELECT * from t1 WHERE ts = 1 AND color = 'GREEN';
DROP TABLE t1;
......@@ -48,7 +48,6 @@ int heap_delete(HP_INFO *info, const uchar *record)
pos[share->reclength]=0; /* Record deleted */
share->deleted++;
share->key_version++;
info->current_hash_ptr=0;
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
#endif
......@@ -182,21 +181,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;
......
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