Commit 6a2d730a authored by Michael Widenius's avatar Michael Widenius

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

parent 08ba2578
...@@ -738,3 +738,23 @@ SELECT c2 FROM t1; ...@@ -738,3 +738,23 @@ SELECT c2 FROM t1;
c2 c2
0 0
DROP TABLE t1; 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;
id color ts
7 GREEN 2
DROP TABLE t1;
...@@ -485,3 +485,30 @@ INSERT INTO t1 VALUES('', 0); ...@@ -485,3 +485,30 @@ INSERT INTO t1 VALUES('', 0);
ALTER TABLE t1 MODIFY c1 VARCHAR(101); ALTER TABLE t1 MODIFY c1 VARCHAR(101);
SELECT c2 FROM t1; SELECT c2 FROM t1;
DROP TABLE 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;
DROP TABLE t1;
# End of 5.1 tests
...@@ -47,7 +47,6 @@ int heap_delete(HP_INFO *info, const uchar *record) ...@@ -47,7 +47,6 @@ int heap_delete(HP_INFO *info, const uchar *record)
share->del_link=pos; share->del_link=pos;
pos[share->reclength]=0; /* Record deleted */ pos[share->reclength]=0; /* Record deleted */
share->deleted++; share->deleted++;
info->current_hash_ptr=0;
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG) #if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0);); DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
#endif #endif
...@@ -180,21 +179,50 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, ...@@ -180,21 +179,50 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
} }
pos2= hp_mask(lastpos_hashnr, blength, share->records + 1); pos2= hp_mask(lastpos_hashnr, blength, share->records + 1);
if (pos2 == hp_mask(pos_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) 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); 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); DBUG_RETURN(0);
} }
pos3= pos; /* Link pos->next after lastpos */ /*
} Shrinking the hash table deleted the main bucket entry for this hash.
else 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
pos3= 0; /* Different positions merge */ that heap_rnext() works.
keyinfo->hash_buckets--;
- 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]; empty[0]=lastpos[0];
hp_movelink(pos3, empty, pos->next_key); hp_movelink(pos3, empty, pos->next_key);
pos->next_key=empty; 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