Commit 84a9e656 authored by svoj@mysql.com/june.mysql.com's avatar svoj@mysql.com/june.mysql.com
Browse files

BUG#30590 - delete from memory table with composite btree primary key

DELETE query against memory table with btree index may remove
not all matching rows. This happens only when DELETE uses
index read method to find matching rows. E.g. for queries
like DELETE FROM t1 WHERE a=1.

Fixed by reverting fix for BUG9719 and applying proper solution.
parent 45647d3b
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -73,10 +73,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
  int res;

  if (flag) 
  {
    info->last_pos= NULL; /* For heap_rnext/heap_rprev */
    info->lastkey_len= 0;
  }

  custom_arg.keyseg= keyinfo->seg;
  custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
+11 −0
Original line number Diff line number Diff line
@@ -36,6 +36,17 @@ int heap_rfirst(HP_INFO *info, byte *record, int inx)
	     sizeof(byte*));
      info->current_ptr = pos;
      memcpy(record, pos, (size_t)share->reclength);
      /*
        If we're performing index_first on a table that was taken from
        table cache, info->lastkey_len is initialized to previous query.
        Thus we set info->lastkey_len to proper value for subsequent
        heap_rnext() calls.
        This is needed for DELETE queries only, otherwise this variable is
        not used.
        Note that the same workaround may be needed for heap_rlast(), but
        for now heap_rlast() is never used for DELETE queries.
      */
      info->lastkey_len= 0;
      info->update = HA_STATE_AKTIV;
    }
    else
+29 −0
Original line number Diff line number Diff line
@@ -34,11 +34,40 @@ int heap_rnext(HP_INFO *info, byte *record)
    heap_rb_param custom_arg;

    if (info->last_pos)
    {
      /*
        We enter this branch for non-DELETE queries after heap_rkey()
        or heap_rfirst(). As last key position (info->last_pos) is available,
        we only need to climb the tree using tree_search_next().
      */
      pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos,
                             offsetof(TREE_ELEMENT, left),
                             offsetof(TREE_ELEMENT, right));
    }
    else if (!info->lastkey_len)
    {
      /*
        We enter this branch only for DELETE queries after heap_rfirst(). E.g.
        DELETE FROM t1 WHERE a<10. As last key position is not available
        (last key is removed by heap_delete()), we must restart search as it
        is done in heap_rfirst().

        It should be safe to handle this situation without this branch. That is
        branch below should find smallest element in a tree as lastkey_len is
        zero. tree_search_edge() is a kind of optimisation here as it should be
        faster than tree_search_key().
      */
      pos= tree_search_edge(&keyinfo->rb_tree, info->parents,
                            &info->last_pos, offsetof(TREE_ELEMENT, left));
    }
    else
    {
      /*
        We enter this branch only for DELETE queries after heap_rkey(). E.g.
        DELETE FROM t1 WHERE a=10. As last key position is not available
        (last key is removed by heap_delete()), we must restart search as it
        is done in heap_rkey().
      */
      custom_arg.keyseg = keyinfo->seg;
      custom_arg.key_length = info->lastkey_len;
      custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
+7 −0
Original line number Diff line number Diff line
@@ -307,4 +307,11 @@ UNIQUE USING BTREE(c1)
) ENGINE= MEMORY DEFAULT CHARSET= utf8;
INSERT INTO t1 VALUES('1'), ('2');
DROP TABLE t1;
CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY;
INSERT INTO t1 VALUES(1),(2),(2);
DELETE FROM t1 WHERE a=2;
SELECT * FROM t1;
a
1
DROP TABLE t1;
End of 4.1 tests
+9 −0
Original line number Diff line number Diff line
@@ -213,4 +213,13 @@ CREATE TABLE t1 (
INSERT INTO t1 VALUES('1'), ('2');
DROP TABLE t1;

#
# BUG#30590 - delete from memory table with composite btree primary key
#
CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY;
INSERT INTO t1 VALUES(1),(2),(2);
DELETE FROM t1 WHERE a=2;
SELECT * FROM t1;
DROP TABLE t1;

--echo End of 4.1 tests